认识Dom渲染过程

思考 🤔

可以直观的通过手段查看 dom 的重绘重排么?

熟悉 Chrome 调试工具

Chrome 控制台远比你想象中的强大

chrome_performance_test

先看来一段神奇的代码,查看测试代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* css in js */
      /* :root{
        --test:()=>{
          console.log(123);
        }
      } */
      .container {
        position: relative;
        min-height: 400px;
      }
      .ball {
        position: absolute;
        top: 0;
        left: 0;
        width: 100px;
        height: 100px;
        border-radius: 50%;
        box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.75);
      }
      .ball-running {
        animation: run-around 4s infinite;
      }
      @keyframes run-around {
        0% {
          /* top: 0;
          left: 0; */
          transform: translate(0, 0);
        }
        25% {
          /* top: 0;
          left: 200px; */
          transform: translate(200px, 0);
        }
        50% {
          /* top: 200px;
          left: 200px; */
          transform: translate(200px, 200px);
        }
        75% {
          /* top: 200px;
          left: 0; */
          transform: translate(0, 200px);
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="ball" id="ball"></div>
    </div>
    <script>
      var balls = document.getElementById('ball');
      balls.classList.add('ball');
      balls.classList.add('ball-running');
    </script>
  </body>
</html>

小结

在开发者工具,Performance -> Event log 中 可以看到

使用 top left 会发现不断的 重绘和重排 (绿色的是重绘,紫色的是重排)

使用 transform 则没有,在第一次渲染后就不会再进行重绘重排了,可以在Summary中看到idle空闲的时间占很大一部分

浏览器渲染过程

网页整个渲染流程

  1. 浏览器的Dom分层的,网页是3D的

  2. 对DOM元素节点计算样式结果Recalculate Style 样式重计算

  3. 为每个节点生成图形位置Layout回流重排

  4. 将每个节点绘制填充到图层位图中Paint

  5. 图层作为纹理上传到GPU

  6. Composite Layers合成层把符合图层生成到页面上

    • Layout

    • Paint

  7. Composite Layers 做了什么?

    • 图层的绘制列表,准备好,主线程 commit 合成线程

    • 合成线程viewport划分图块 256*256

    • 生成我们的位图的过程栅格化(光栅化) raster

    • 所有图块 CPU 合成生成 DarwQuad 提交给浏览器渲染进程

    • viz组件 接收到 DarwQuad 绘制到我们的屏幕上

什么是光栅化?

把文档的结构、元素的样式、几何形状和绘制顺序转换为屏幕上的像素。通俗一点来说,就是将图片转化成一个个栅格组成的图像。

分层

会触发元素分层

根元素、position分层、transform、半透明、CSS滤镜、canvas、video、overflow

GPU参与进来(css 3d硬件加速)

CSS3D、Video、webgl、transform、css滤镜、willl-change:transfrom

重绘和重排(盒子动了必定重排)

  • offset,scroll,client,width 读取,都会打断浏览器工作。造成重排。

  • 优化: requestAnimationFrame 下一帧去写(react利用了他:设置dom元素,读写分离

  • cpu负责操作系统和程序和数据处理

  • gpu负责显示 数据处理 效率更高

  • fastdom,管理dom,控制读写分离的插件

  • csstriggers.com 可查看是否引起重排重绘

// 尽量把读操作和写操作放到一起,或者在下一帧执行写操作:

const width = doucument.getElementbyid("xx").width;

requestAnimationFrame(function(){
  // react
  // 设置dom元素 读写分离
})

cpu主要负责操作系统和程序,gpu负责显式 数据处理 效率更高 gpu.js

fastdom 控制读写分离的插件open in new window

csstriggers 可查看是否引起重排重绘open in new window

参考流程

样式流程

rendering-process-summary-1rendering-process-summary-2rendering-process-summary-3

渲染进程

rendering-process-summary-4

结论

能使用 CSS 3D硬件加速的地方尽量使用,以此优化Dom的性能,极大的减少Dom的重绘重排

Last Updated:
Contributors: kk