性能优化之渲染优化
本文最后更新于:2021/07/05 , 星期一 , 21:32
浏览器渲染过程(对应面试题:从用户输入url到显示都发生了什么)
省略网络相关部分。
渲染进程将 HTML 内容转换为能够读懂的 DOM 树结构。
渲染引擎将 CSS 样式表转化为浏览器可以理解的 styleSheets,计算出 DOM 节点的样式。
创建布局树,并计算元素的布局信息。
对布局树进行分层,并生成分层树。
为每个图层生成绘制列表,并将其提交到合成线程。
合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。
合成线程发送绘制图块命令 DrawQuad 给浏览器进程。
浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。
主流程:DOM -》Style-》Layout-》Layer-》Paint
布局
重排(回流)和重绘
通过 JavaScript 或者 CSS 修改元素的几何位置属性,例如改变元素的宽度、高度等,那么浏览器会触发重新布局,解析之后的一系列子阶段(即从上文序号2开始),这个过程就叫重排。
通过 JavaScript 或者 CSS 修改元素没有引起几何位置的变换(即绘制属性(元素的颜色、背景色、边框等)),布局阶段将不会被执行,直接进入了绘制阶段,然后执行之后的一系列子阶段(即跳过序号3,4),这个过程就叫重绘。
影响重排(回流)的操作
添加/删除元素
操作styles
display:none
offsetLeft,scrollTop,clientWidth
移动元素位置
修改浏览器大小,字体大小。
批量添加DOM时可以使用DocumentFragment
避免Layout thrashing
避免重排(回流)
读写分离:FastDom,原理:读写分离,批量操作,使用window.requestAnimationFrame。
减少重绘的方案
利用DevTools识别paint的瓶颈
利用will-change创建新图层
触发合成过程的属性
渲染引擎将跳过布局和绘制,只执行后续的合成操作,这个过程叫做合成。
位置:transform:translate
缩放:transform:scale
旋转:transform:rotate
透明度:opacity
使用Flexbox优化布局
栅格方案性能对比(float vs flex):分别用float 和 flex实现渲染10w个大小一样的div块,然后使用ChromDevTools-Performance进行查看
float:rendering(Recalculate+Layout):1804ms Painting:60ms
flex:rendering(Recalculate+Layout):1267ms Painting:34ms
flexbox优势:
更高性能的实现方式
容器有能力决定子元素的大小,顺序,对齐,间隔等。
双向布局
高频事件处理
防抖
任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
比如当监听鼠标移动等事件时:
1 |
|
1 |
|
React时间调度实现
React Fiber:把更新过程碎片化,每执行完一段更新过程,就把控制权交还给React负责任务协调的模块,看看有没有其他紧急任务要做,如果没有就继续去更新,如果有紧急任务,那就去做紧急任务。
基本原理
requestIdleCallback的问题:兼容性不好。在浏览器的空闲时段内调用的函数排队,能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件。
通过rAF模拟rIC:在requestAnimationFrame获取一桢的开始时间,触发一个postMessage,在空闲的时候调用idleTick来完成异步任务。
预渲染
react可以使用react-snap
1 |
|
原理:使用 Headless Chrome爬取页面的内容(模拟搜索引擎的爬虫?),然后内容直接放到build的html中。
预渲染的作用
大型单页应用的性能瓶颈:JS下载+解析+执行
SSR的主要问题:牺牲TTFB来补救First Paint;实现复杂;
Pre-rendering打包时提前渲染页面,没有服务端参与。
可能存在的问题:
- 内联样式,不经过配置会出现明显的样式闪动。(可以针对首屏把CSS提取出来内嵌到HTML中,剩下的CSS用webpack提取到文件中,进行缓存)
可视化窗口(windowing)提高列表性能 - 虚拟列表
只渲染可见的行,渲染和滚动的性能都会提升
减少了呈现初始视图和处理更新所需的工作量和时间
避免了 DOM 节点的过度分配,从而减少了内存占用(Lazy loading时,dom会变得非常大)
使用骨架组件减少布局移动(Layout shift)
主要作用就是占位,与要显示的组件大小一样大,等数据加载完成后再显示数据。可以提升用户感知性能
首屏渲染优化方案
首屏 - 用户加载的3个关键时刻
对应的测量指标:
First Contentful Paint(FCP)—– is it happening?(网络请求是否发送出去了?)
Largest Contentful Paint(LCP)—– is it useful?(网页内容是否对我有用?)
Time To Interactive (TTI) —– is it usable?(是否可以交互了?)
方案:
资源体积太大?资源压缩,传输压缩,代码拆分,Tree shaking,HTTP/2,缓存
首页内容太多?路由/组件/内容懒加载,预渲染/SSR,Inline CSS
加载顺序不合适? prefetch,preload
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!