Open yanyue404 opened 2 years ago
前面有提到 http 交互,那么接下来就是浏览器获取到 html,然后解析,渲染
这部分很多都参考了网上资源,特别是图片,参考了来源中的文章
浏览器内核拿到内容后,渲染步骤大致可以分为以下几步:
1. 解析HTML,构建DOM树 2. 解析CSS,生成CSS规则树 3. 合并DOM树和CSS规则,生成render树 4. 布局render树(Layout/reflow),负责各元素尺寸、位置的计算 5. 绘制render树(paint),绘制页面像素信息 6. 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上
如下图:
整个渲染步骤中,HTML 解析是第一步。
简单的理解,这一步的流程是这样的:浏览器解析 HTML,构建 DOM 树。
但实际上,在分析整体构建时,却不能一笔带过,得稍微展开。
解析 HTML 到构建出 DOM 当然过程可以简述如下:
Bytes → characters → tokens → nodes → DOM
譬如假设有这样一个 HTML 页面:(以下部分的内容出自参考来源,修改了下格式)
<html> <head> <meta name="viewport" content="width=device-width,initial-scale=1"> <link href="style.css" rel="stylesheet"> <title>Critical Path</title> </head> <body> <p>Hello <span>web performance</span> students!</p> <div><img src="awesome-photo.jpg"></div> </body> </html>
浏览器的处理如下:
列举其中的一些重点过程:
1. Conversion转换:浏览器将获得的HTML内容(Bytes)基于他的编码转换为单个字符 2. Tokenizing分词:浏览器按照HTML规范标准将这些字符转换为不同的标记token。每个token都有自己独特的含义以及规则集 3. Lexing词法分析:分词的结果是得到一堆的token,此时把他们转换为对象,这些对象分别定义他们的属性和规则 4. DOM构建:因为HTML标记定义的就是不同标签之间的关系,这个关系就像是一个树形结构一样 例如:body对象的父节点就是HTML对象,然后段略p对象的父节点就是body对象
最后的 DOM 树如下:
同理,CSS 规则树的生成也是类似。简述为:
Bytes → characters → tokens → nodes → CSSOM
譬如style.css内容如下:
style.css
body { font-size: 16px } p { font-weight: bold } span { color: red } p span { display: none } img { float: right }
那么最终的 CSSOM 树就是:
当 DOM 树和 CSSOM 都有了后,就要开始构建渲染树了
一般来说,渲染树和 DOM 树相对应的,但不是严格意义上的一一对应
因为有一些不可见的 DOM 元素不会插入到渲染树中,如 head 这种不可见的标签或者display: none等
display: none
整体来说可以看图:
有了 render 树,接下来就是开始渲染,基本流程如下:
图中重要的四个步骤就是:
1. 计算CSS样式 2. 构建渲染树 3. 布局,主要定位坐标和大小,是否换行,各种position overflow z-index属性 4. 绘制,将图像绘制出来
然后,图中的线与箭头代表通过 js 动态修改了 DOM 或 CSS,导致了重新布局(Layout)或渲染(Repaint)
这里 Layout 和 Repaint 的概念是有区别的:
回流的成本开销要高于重绘,而且一个节点的回流往往回导致子节点以及同级节点的回流, 所以优化方案中一般都包括,尽量避免回流。
什么会引起回流?
1.页面渲染初始化 2.DOM结构改变,比如删除了某个节点 3.render树变化,比如减少了padding 4.窗口resize 5.最复杂的一种:获取某些属性,引发回流, 很多浏览器会对回流做优化,会等到数量足够时做一次批处理回流, 但是除了render树的直接变化,当获取一些属性时,浏览器为了获得正确的值也会触发回流,这样使得浏览器优化无效,包括 (1)offset(Top/Left/Width/Height) (2) scroll(Top/Left/Width/Height) (3) cilent(Top/Left/Width/Height) (4) width,height (5) 调用了getComputedStyle()或者IE的currentStyle
回流一定伴随着重绘,重绘却可以单独出现
所以一般会有一些优化方案,如:
documentFragment
transform
will-change
translate
再来看一个示例:
var s = document.body.style; s.padding = "2px"; // 回流+重绘 s.border = "1px solid red"; // 再一次 回流+重绘 s.color = "blue"; // 再一次重绘 s.backgroundColor = "#ccc"; // 再一次 重绘 s.fontSize = "14px"; // 再一次 回流+重绘 // 添加node,再一次 回流+重绘 document.body.appendChild(document.createTextNode('abc!'));
CSS 的标签与 JS 的 Githubissues. Githubissues is a development platform for aggregating issues.
大纲
解析页面流程
前面有提到 http 交互,那么接下来就是浏览器获取到 html,然后解析,渲染
这部分很多都参考了网上资源,特别是图片,参考了来源中的文章
流程简述
浏览器内核拿到内容后,渲染步骤大致可以分为以下几步:
如下图:
HTML 解析,构建 DOM
整个渲染步骤中,HTML 解析是第一步。
简单的理解,这一步的流程是这样的:浏览器解析 HTML,构建 DOM 树。
但实际上,在分析整体构建时,却不能一笔带过,得稍微展开。
解析 HTML 到构建出 DOM 当然过程可以简述如下:
譬如假设有这样一个 HTML 页面:(以下部分的内容出自参考来源,修改了下格式)
浏览器的处理如下:
列举其中的一些重点过程:
最后的 DOM 树如下:
生成 CSS 规则
同理,CSS 规则树的生成也是类似。简述为:
譬如
style.css
内容如下:那么最终的 CSSOM 树就是:
构建渲染树
当 DOM 树和 CSSOM 都有了后,就要开始构建渲染树了
一般来说,渲染树和 DOM 树相对应的,但不是严格意义上的一一对应
因为有一些不可见的 DOM 元素不会插入到渲染树中,如 head 这种不可见的标签或者
display: none
等整体来说可以看图:
渲染
有了 render 树,接下来就是开始渲染,基本流程如下:
图中重要的四个步骤就是:
然后,图中的线与箭头代表通过 js 动态修改了 DOM 或 CSS,导致了重新布局(Layout)或渲染(Repaint)
这里 Layout 和 Repaint 的概念是有区别的:
回流的成本开销要高于重绘,而且一个节点的回流往往回导致子节点以及同级节点的回流, 所以优化方案中一般都包括,尽量避免回流。
什么会引起回流?
回流一定伴随着重绘,重绘却可以单独出现
所以一般会有一些优化方案,如:
documentFragment
或 div,在它上面应用所有 DOM 操作,最后再把它添加到 window.document,避免多次读取 offset 等属性。无法避免则将它们缓存到变量transform
、will-change
等,比如改变元素位置,我们使用translate
会比使用绝对定位改变其 left 、top 等来的高效,因为它不会触发重排或重绘,transform
使浏览器为元素创建⼀个 GPU 图层,这使得动画元素在一个独立的层中进行渲染。当元素的内容没有发生改变,就没有必要进行重绘。再来看一个示例:
CSS 的标签与 JS 的 Githubissues.Githubissues is a development platform for aggregating issues.