DOM
CSSOM
RenderTree
Layout
Paint
[图片上传失败...(image-a35366-1526004305368)]
转换: 浏览器从磁盘或网络读取 HTML 的原始字节,并根据文件的指定编码(例如 UTF-8)将它们转换成各个字符。
令牌化(Token): 浏览器将字符串转换成 W3C HTML5 标准规定的各种令牌,例如,“
”、“”,以及其他尖括号内的字符串。每个令牌都具有特殊含义和一组规则。词法分析(Node): 发出的令牌转换成定义其属性和规则的“对象”(我理解成标签)。
DOM 构建: 最后,由于 HTML 标记定义不同标记之间的关系(一些标记包含在其他标记内),创建的对象链接在一个树数据结构内,此结构也会捕获原始标记中定义的父项-子项关系:HTML 对象是 body 对象的父项,body 是 paragraph 对象的父项,依此类推。
注:DOM 是增量构建,没有必要等到 DOM 构建完成之后在渲染到页面
[图片上传失败...(image-c50f77-1526004305369)]
与 DOM 的流程类似,只不过它是 CSSOM
[图片上传失败...(image-e6dc0b-1526004305369)]
上图说明 CSSOM 为啥是树形结构
[图片上传失败...(image-571272-1526004305369)]
从 DOM 树的根节点开始遍历每个可见节点。
某些节点不可见(例如脚本标记、元标记等),因为它们不会体现在渲染输出中,所以会被忽略。
某些节点通过 CSS 隐藏,因此在渲染树中也会被忽略,例如,上例中的 span 节点---不会出现在渲染树中,---因为有一个显式规则在该节点上设置了“display: none”属性。
节点位置和大小是基于 viewport 计算的
对于每个可见节点,为其找到适配的 CSSOM 规则并应用它们。
发射可见节点,连同其内容和计算的样式。
最终输出的渲染同时包含了屏幕上的所有可见内容及其样式信息
注:简单提一句,请注意 visibility: hidden 与 display: none 是不一样的。前者隐藏元素,但元素仍占据着布局空间(即将其渲染成一个空框),而后者 (display: none) 将元素从渲染树中完全移除,元素既不可见,也不是布局的组成部分。
总结:
到目前为止(以上 3 步骤),我们计算了哪些节点应该是可见的以及它们的计算样式,但我们尚未计算它们在设备视口内的确切位置和大小---这就是“布局”阶段 Layout,也称为“自动重排”。
Render Tree 会等到 CSSOM 构建完在执行,因为 css 是增量构建,但不是增量渲染的。浏览器不能先渲染 14px 字,又接着渲染 18px,发现又变量,渲染成 16px
为弄清每个对象在网页上的确切大小和位置,浏览器从渲染树的根节点开始进行遍历。
执行渲染树构建、布局和绘制所需的时间将取决于文档大小、应用的样式,以及运行文档的设备:文档越大,浏览器需要完成的工作就越多;样式越复杂,绘制需要的时间就越长(例如,单色的绘制开销“较小”,而阴影的计算和渲染开销则要“大得多”)。
查看哪些样式触发 Layout:https://csstriggers.com/
屏幕旋转
浏览器视窗改变
与大小位置相关的 CSS 属性改变
布局完成后,浏览器会立即发出“Paint Setup”和“Paint”事件,将渲染树转换成屏幕上的像素(,也就是填充)
img
css
js
font
浏览器会在何时渲染页面:加载完部分 DOM 和 CSSOM
上面 2 种形式都会阻止初次渲染
浏览器会在解析完 CSS 后,在进行渲染,为了防止样式突变带来的抖动
不管 CSS 出现在文档哪里,都会阻塞整个文档初次渲染
通过 link 标签,阻塞时间更长,因为有个网络请求时间
重点:关键资源
document.write 写入 link 标签,阻止渲染
css 是不是关键资源,看媒体查询
如果不是当前网页所应用的类型文件,虽然也会加载,但是不会阻塞初次渲染
通过 DOM api 添加 link 不会阻塞渲染
JS 阻塞 HTML 渲染
因为 js 有修改 dom 的能力,所以浏览器会在执行 js 期间,暂停 html 渲染
CSS 阻塞 JS
因为 JS 能读取或者修改 CSS,所以要等到 CSS 加载完在执行
当 HTML 被 JS 阻塞了,虽然停止构建 DOM,但是浏览器还是会识别 JS 后面的资源,并提前加载他们,
这是浏览器的资源加载策略
重点:关键资源
放到底部,‘延时’加载
使用 defer 延迟脚本执行。拥有 defer 的脚本,会被推迟到 HTML 文档解析完成后,在执行;并且执行的顺序是按照 HTML 文档中出现的顺序。
不会阻塞初次渲染
放的越前面,越能提前加载
不好的地方:执行顺序。如果前面加载 1M 的 js 文件,这个不加载完,后面的就算加载完也执行不了
使用 async 异步加载脚本
不会阻塞初次渲染,也不会被 CSS 阻塞
脚本加载完就执行,所以跟在 HTML 文档中的顺序无关
适用于无依赖的 js
[图片上传失败...(image-cddec-1526004305369)]
阻塞初次渲染,页面空白。所以要异步加载 css,因为字体是定义在 css 里的
目标:以下压缩到最低
关键资源数
关键资源体积
关键资源网络来回数
延迟或异步加载资源,从而减少关键资源数
减小资源大小
针对关键资源,减少网络请求时间
浏览器无需等待 HTML 加载完毕,就开始构建 DOM
禁用缓存(Network 里 Disable cache),以便测试首次浏览性能
关闭 Chrome 扩展或者直接使用隐身模式
模拟真实网络情况
Chrome Canary(Chrome 开发版本)
作者:辉lazy
链接:https://www.jianshu.com/p/424d2179ea9b
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/1273/viewspace-2814465/ ,如需转载,请注明出处,否则将追究法律责任。