图片引自Mariko Kosaka的《Inside look at modern web browser》
图片引自Mariko Kosaka的《Inside look at modern web browser》
解决方法
- 将JS操作划分成小块,并安排在每个帧上运行 window.requestAnimationFrame(renderFunc)。兼容版本:https://github.com/darius/requestAnimationFrame
优点:
1) 省CPU时间:页面隐藏最小化时停止渲染,setTimeout持续运行。
2) 函数节流:高频率事件(resize/scroll)为防止刷新间隔内多次执行函数,只执行一次更流畅,省开销。
// 节流(throttle) 去抖(debounce) // 把要执行的函数放在延时器中执行且只执行最后一次,且判断距上次执行的时间大于延时执行时间 function show() {} let lastTime = new Date(); let delay = 200; let timer = null; document.body.onscroll = function () { if (document.documentElement.scrollTop >= 1000) { let now = new Date(); if (now - lastTime > delay) { // 去抖 timer = setTimeout(show, 200); } else { clearTimeout(timer); // 节流 timer = setTimeout(show, 200); } lastTime = new Date(); } };
- 将非dom操作的运行任务放在webWorker中运行,避免阻塞主线程
// 任务文件 demo_workers.js var i = 0; function timedCount() { i = i 1; postMessage(i); // 向页面发送数据 } setInterval(timedCount, 500); // 包含dom的页面 index.html let w = new window.Worker('demo_workers.js'); // 开始 w.onmessage = function (event) { document.getElementById('result').innerHTML = event.data; }; w.terminate(); // 停止
7. 合成
浏览器知道文档的结构,每个元素的样式,页面的几何形状和绘制顺序,需将信息转换为屏幕上的像素,称为光栅化。
在视口内部使用栅格部件 - chrome首次发布时处理栅格化的方式用户滚动页面,则移动光栅框架,并通过更多光栅填充缺失的部分
合成是一种将页面的各个部分分层,分别栅格化,并在合成器线程的单独线程中合成为页面的技术。如果发生滚动,图层已经被栅格化需要合成一个新帧。通过移动图层和合成新帧,可以以相同的方式实现动画。
7.1 分层
为了找出哪些元素需要在哪些层中,主线程遍历布局树以创建层树。如果页面的某些部分应该是单独的图层(如滑入式侧面菜单)但没有得到单独图层,可以使用CSS属性will-change提示浏览器。https://developer.mozilla.org/zh-CN/docs/Web/CSS/will-change
过多的图层:过多图层合成可能会导致比页面小部分每帧光栅化更慢。
图片引自Mariko Kosaka的《Inside look at modern web browser》
7.2 光栅和复合关闭主线程
1) 提交合成:一旦创建了层树并确定了绘制顺序,主线程就会将该信息提交给合成器线程。
2) 栅格化:合成器线程然后栅格化每个层。一个图层可能像页面的整个长度一样大,因此合成器线程将它们分成多个图块并将图块发送到栅格线程。
3) 栅格存储:栅格线程栅格化每个图块并将它们存储在GPU内存中。
4) 绘制四边形:一旦图块被光栅化,绘制四边形的图块信息(图块在内存中的位置、绘制图块页面中的位置)
5) 合成框架:合成器线程可以优先考虑视口(或附近)内的删格线程,以便优先被光栅化。图层还有不同分辨率的倾斜度,可以处理放大操作。
6) 创建合成器帧:收集绘制四边形的图块信息,通过IPC将合成器框架提交给浏览器进程
7) 浏览器UI合成:UI线程添加另一个合成器框架以用于浏览器UI更改,或者从其他渲染器进程添加扩展。
8) GPU展示:合成器帧被发送到GPU以在屏幕上显示。
9) 滚动事件:合成器线程会创建另一个合成器帧以发送到GPU
图片引自Mariko Kosaka的《Inside look at modern web browser》
创建磁贴位图并发送到GPU的栅格线程