zoukankan      html  css  js  c++  java
  • 基于Webkit的浏览器关键渲染路径介绍

    关键渲染路径概念

    浏览器是如何将HTML、JS、CSS、image等资源渲染成可视化的页面的呢?本文简单介绍一下渲染过程中涉及到的关键步骤。

    该过程分为四步:模型对象的构建、渲染树构建、布局、绘制。

     

    1.模型对象的构建

    浏览器获取到HTML、CSS文件后,需要对其进行解析,抽象成DOM和CSSOM对象,然后提供相应的JS API,方便开发者进行交互逻辑开发。

    HTML文件字节转变成DOM的过程如下图所示:

    主要经历字符编码—》令牌提取标签—》词法分析转变成DOM对象—》依照标签的嵌套关系构建成DOM树;

     

    CSS文件字节转变成CSSOM的过程与HTML转DOM类似,区别就是按照规则通用性建立树形关系。

    2.渲染树的构建

    所谓渲染树,就是将DOM树和CSSOM树合并,得到每个可见元素的内容和显示样式。

    Tips:

    (1)渲染树并非显示所有元素,而只是占据空间元素,如display: none的元素不在渲染树中,而visibility: hidden的在渲染树中;

    (2)渲染树包含的内容只是元素的内容及其样式信息,在不同视口(viewport,也就是浏览器的屏幕画布)下实际展示肯能会有差别;

    (3)渲染树构建后,Webkit还会继续构建渲染层(RenderLayer),这是为了简化渲染逻辑,同时方便开发者查看网页层次。

    3.布局

    经过前两步的操作,我们知道了元素的内容和样式信息,但是实际在不同显示器中的大小和位置如何确定呢,这就需要进行布局操作了,有的地方称为"自动重排"(reflow)。Webkit依据框模型来计算元素的位置和大小,布局输出的是一个"盒模型"对象,该对象包含了每个元素在视口内的确切位置和尺寸。

     

    4.绘制

    在布局结束后,接下来就是绘制,实现栅格化。绘制一般涉及到Paint和Composite Layers。

    Paint一般通过图像上下文来控制,分为2D和3D绘制上下文。

    前文提到了RenderLayer的概念,绘制过程中,每个RenderLayer是输出图像中的一层,各个层根据深度信息组合成一张图像,这个组合的过程称为Composite Layers。

     

    关键渲染路径开发相关

    介绍完了关键渲染路径的概念,接下来结合chrome dev-tool来看一下实际的情况,chrome的版本是60.0。

    1.代码

    <html>
    <head>
        <title>Janky Animation</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" type="text/css" href="index.css"/>
        <link rel="stylesheet" type="text/css" href="https://ss1.bdstatic.com/
        5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/soutu/css/soutu.css"/>
    </head>
    <body>
        <img class="proto mover" src="./images/logo-1024px.png"/>
        <div class="controls">
            <button class="add"></button>
            <button class="subtract" disabled></button>
            <button class="stop">Stop</button>
            <button class="optimize">Optimize</button>
            <button class="optimize-fastdom">Optimize By Fastdom</button>
            <a href="https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/"
               target="_blank">
                <button class="optimize">Help</button>
            </a>
        </div>
        <script src="./libs/fastdom.js"></script>
        <script src="index.js"></script>
    </body>
    </html>
    

      

    2.使用performance调试

    为了避免chrome插件的干扰,建议使用【隐身窗口】打开页面,然后打开dev-tool,选择Performance进行调试

    3.main线程的使用情况

    渲染的关键路径主要体现在主线程中,如下图所示。

    图中的蓝色的Parse HTML表示DOM的构建过程,蓝色的Parse StyleSheet代表CSSOM的构建过程,黄色的Evaluate Script表示JS的执行过程,紫色的Recalculate Style表示构建Render Tree的过程,紫色的Layout表示布局过程。

    (1)单线程

    虽然资源的下载可以并行,但是资源的解析是单线程的,主要通过Main线程来解析,由下图所示,ParseHTML被JS的解析阻塞,分成了三段。线程的使用情况和代码中的资源的位置有很大关系,这个下面会介绍。

    (2)时间线事件

    Main线程中的图中,有一些细线条记录着一些事件的触发时间,光标放在上面就可以查看。事件主要分为Loading、Scripting、Redering、Painting四大类,具体可以查看官方介绍。其中Scripting类型中有一种Event类型的事件,如下图中的Event(DOMCotentLoaded)可以在JS中被监听到,常用的还有readystatechange、pageshow、pagehide、loaded、webkitvisiblechange等,最近有一个项目中pageshow事件就帮我解决了IOS WKWebview回退页面缓存不刷新的问题。

      

    Tips:

    (1)HTML文件中JS文件、CSS文件的位置

    通常我们会将css文件放在head标签中,JS文件放置在body标签的后面,这是有一定道理的。由于JS执行的过程中可能修改DOM和CSS样式,这也就造成了Evaluate Script的执行会阻塞Parse HTML的过程,如果JS中引用未解析到的DOM程序就会报错;如果script标签之前有引入css文件,Evaluate Script会等到Parse Stylesheet过程结束后再执行。

    所以将CSS文件放置在头部,提前下载并解析;将JS文件放在尾部,让JS尽可能的访问到所有的DOM,避免报错。

    (2)优化渲染路径的重要性

    前端性能优化主要分为网络请求和代码层面两种。网络请求上的方法是压缩合并、按需加载、缓存等;代码层面则就是要优化渲染路径,毕竟单线程要在模型对象构建、渲染树构建、布局、渲染之间切换,如下图所示。

    优化渲染路径对于页面性能至关重要,接下来会写几篇文章针对不同阶段给出优化方法,敬请期待。

      

  • 相关阅读:
    Java实现 LeetCode 735 行星碰撞(栈)
    Java实现 LeetCode 735 行星碰撞(栈)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 蓝桥杯算法提高 求最大值
    Java实现 蓝桥杯算法提高 求最大值
    Java实现 蓝桥杯算法提高 求最大值
    Python eval() 函数
    Python repr() 函数
  • 原文地址:https://www.cnblogs.com/wmhuang/p/7435639.html
Copyright © 2011-2022 走看看