学习笔记,原创内容,谢谢支持(git项目验证地址:https://github.com/victory820/validatejs_css)
渲染引擎
主要模块
HTML 解析器
|
解析 html 文档,主要将 html 解释成 DOM 树
|
CSS 解析器
|
为 DOM 的各个元素计算样式信息,为布局提供基础设施
|
JS 引擎
|
可以修改网页内容,也能修改 css 信息,通过 dom 接口和 css 接口来修改网页内容和样式
|
布局模块(layout)
|
在 DOM 创建后,内核(chrome 为例 webkit)将元素对象和样式结合起来,计算它们的大小位置等布局信息,形成一个能表达所有信息的内部表示模型
|
绘图模块
|
将布局计算后的各个网页节点绘制成图像结果
|
大致的渲染过程
- 遇见 HTML 标记调用 HTML 解析器解析为对应 token(一个 token 就是标签文本的序列化,构建的 dom 树就是一块内存保存着 token 信息与标记的关系)
遇见 style/link 标记调用
- 遇见 script 标记调用 js 引擎,处理 script 标记、绑定事件、修改 dom 树/css 树等
- 将 dom 树和 css 树合并成一个渲染树
- 根据渲染树渲染,计算每个节点的几何信息(依赖 GPU)
- 最终将各个节点绘制到屏幕上
阻塞渲染
css 阻塞
- style 形式和 link 形式
style 标签中内容
|
link 引入内容
|
由 html 解析器解析
|
由 css 解析器解析
|
不阻塞浏览器渲染
|
阻塞浏览器渲染
|
不阻塞 DOM 解析
|
不阻塞 DOM 解析
|
|
阻塞后面 js 的执行
|
- 优化
- 使用 cdn 方式进行加速
- 对 css 进行压缩
- 减少 http 请求,合并 css(辩证看待)
- 优化样式代码
js 阻塞
- 阻塞后续 dom 解析。原因:js 是可以操作 dom 的,如果不阻塞可能做无用功
- 阻塞页面渲染。原因:js 可以改变样式,如果不阻塞同样可能做无用功
- 阻塞后续 js 的执行。原因:维护依赖关系
验证
- link 进来的 css 阻塞页面渲染
- link 进来的 css 不阻塞页面解析
- js 阻塞页面渲染
- js 阻塞页面解析
图层
浏览器在渲染一个页面时,会将页面分为很多个图层,图层有大有小上面有一个或多个节点。
图层创建条件
(以 chrome 为例,还有其他暂时只提以下同时也依赖电脑配置和浏览器设置)
1. 拥有具有 3D 变换的 css 属性
2. 使用加速视频解码的 video 节点
3. canvas 节点
4. 拥有 css 加速属性的元素(will-change)
在渲染 DOM 的时候,浏览器的实际工作是:
- 获取 DOM 后分割为多个图层
- 对每个图层的节点计算样式结果(recalculate style 样式重计算)
- 为每个节点生成图形和位置(layout 重排/回流)
- 将每个节点绘制填充到图层位图中(paint 重绘)
- 图层作为纹理上传给 GPU
- 组合多个图层到页面上生成最终屏幕图形(composite layers 图层重组)
重绘 repaint
是一个元素外观的改变所触发的浏览器行为。重绘不会带来重新布局,所以并不一定伴随重排。
重绘是以图层为单位的,图层中某个元素需要重绘,整个图层都会重绘
为了提高性能应该让变化的东西拥有一个自己的图层
触发重绘的属性
-
|
-
|
-
|
color
|
background
|
outline-color
|
border-style
|
background-image
|
outline
|
border-raius
|
background-position
|
outline-style
|
visibility
|
background-repeat
|
outline-width
|
text-decoration
|
background-size
|
box-shadow
|
重排 reflow(回流)
渲染对象在创建完成并添加到渲染树时,并不包含位置和大小信息,计算这些值的过程称为重排
重排大多数情况下会导致重绘。比如改变元素的位置,就会触发重绘和重排
触发重排的属性
-
|
-
|
-
|
width
|
top
|
text-align
|
height
|
bottom
|
overflow-y
|
padding
|
left
|
font-weight
|
margin
|
right
|
overflow
|
display
|
position
|
font-family
|
border-width
|
float
|
line-height
|
border
|
clear
|
vertival-align
|
min-height
|
white-space
|
|
常见触发重排的操作
reflow 的成本比 repaint 高,一个节点的 reflow 很有可能导致子节点甚至父节点及同级节点的 reflow
下面动作很大可能是成本高的
- 增加、删除、修改 DOM 节点时,导致 reflow,repaint
- 移动 dom 位置
- 修改 css 样式
- resize 窗口时
- 修改网页的默认字体
display:none 会触发 reflow
visibility:hidden 只会触发 repaint
优化方案
- 元素位置移动变换时尽量使用 css3 的 transform 来替代 top/left 等操作,变换(transform)和透明度(opacity)的改变仅仅影响图层的组合
- 将多次改变样式属性的操作合并成一次,即不要一条一条修改 dom 样式,预先定义 class 修改 classname
- 将 dom 离线后再修改。先把元素 display:none 后在对隐藏元素进行操作不会引发其他元素重排。
- 利用文档碎片-documentFragment.参照 https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentFragment
- 不要把获取某些 dom 节点的属性值放到循环内当作循环变量。当向浏览器请求 style 信息时,就会让浏览器 flush 队列.如:offsetTop/Left/Width/Height;scrollTop/Left/Width/Height;clientTop/Left/Widht/Height;width/height
- 动画实现过程中,启用 GPU 硬件加速 transform: tranlateZ(0)
- 为动画元素新建图层,提高动画元素的 z-index
- 编写动画时可以使用以下 api
requestAnimationFrame https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame