从输入URL到渲染页面 -- 深入浅出渲染流程(1)

上文我们知道,一旦文档被提交,渲染进程便开始解析页面和加载资源了。
从本文开始,我们分三篇文章来介绍浏览器的渲染流程

按照渲染的先后顺序会经历下面几个阶段:构建 DOM 树、样式计算、布局阶段、分层、绘制、分块、光栅化和合成。

本文我们主要介绍 构建 DOM 树、样式计算、布局阶段这三个部分

构建DOM树

渲染进程收到 HTML 文件是无法直接被渲染引擎理解的,所以要将其转化为渲染引擎能够理解的内部结构,这个结构就是 DOM。
在渲染引擎内部,使用 HTML 解析器(HTMLParser)将 HTML 字节流转换为 DOM 结构。具体的工作流程如下:

  1. 网络进程接收到content-type=“text/html”响应头之后,为该请求创建一个渲染进程。
  2. 渲染进程准备好之后,网络进程和渲染进程之间会建立一个共享数据的管道,渲染进程通过这个管道读取数据,并同时将读取的数据“吐”给 HTML 解析器
  3. 解析器将数据流解析为 DOM树。

    1. 类似Javascript的AST转换,解析器将数据流解析为 DOM的第一步也是通过分词器将字节流转换为 Token
    test
    StartTag test EndTag // 被解析成这样三个Token
    1. 将 Token 解析为 DOM 节点
    2. 将 DOM 节点添加到 DOM 树中

image.png

也正是因为这种流的传输和解析,导致HTML 解析器并不是等整个文档加载完成之后再解析的,而是网络进程加载了多少数据,HTML 解析器便解析多少数据。

与此同时,HTML 解析器维护了一个 Token 栈结构,主要用来计算节点之间的父子关系,生成的 Token 会被按照顺序压到这个栈中。具体的处理规则如下所示(过程有点像那道经典的算法题判断括号是不是匹配解法):

  • 如果压入到栈中的是 StartTag Token,HTML 解析器会为该 Token 创建一个 DOM 节点,然后将该节点加入到 DOM 树中,它的父节点就是栈中相邻的那个元素生成的节点。
  • 如果是文本 Token,那么会生成一个文本节点,然后将该节点加入到 DOM 树中,文本 Token 是不需要压入到栈中,它的父节点就是当前栈顶 Token 所对应的 DOM 节点。
  • 如果是 EndTag 标签,比如是 EndTag div,HTML 解析器会查看 Token 栈顶的元素是否是 StarTag div,如果是,就将 StartTag div 从栈中弹出,表示该 div 元素解析完成。

现在我们有了DOM树之后还远远不够,浏览器还是不知道要如何去“绘画”我们的页面,下面的样式计算部分就是告诉浏览器要如何“绘画”页面

样式计算

我们知道页面中css有三种引入形式:

  • 通过 link 引用的外部 CSS 文件
  • test1
    test2

    该示例中,JavaScript 中 div1.style.color = 'red' 语句用来操纵 CSSOM ,所以在执行 JavaScript 之前,需要先解析 JavaScript 语句之上所有的 CSS 样式。
    所以如果代码里引用了外部的 CSS 文件,那么在执行 JavaScript 之前,还需要等待外部的 CSS 文件下载完成,并解析生成 CSSOM 对象之后,才能执行 JavaScript 脚本。
    而 JavaScript 引擎在解析 JavaScript 之前,是不知道 JavaScript 是否操纵了 CSSOM 的,所以渲染引擎在遇到 JavaScript 脚本时,不管该脚本是否操纵了 CSSOM,都会执行 CSS 文件下载,解析操作,再执行 JavaScript 脚本。所以说 JavaScript 脚本是依赖样式表的。

    这时我们再变一下,把插入的脚本换成引入脚本的方式:

    
    
        
            
        
        
            
    test1
    test2

    我们上图来解释具体的执行过程:
    image.png

    HTML 预解析器识别出来了有 CSS 文件和 JavaScript 文件需要下载,然后就同时发起这两个文件的下载请求(这两个文件的下载过程是重叠的,所以下载时间以最久的为准)。后面的流水线就和前面是一样的了,不管 CSS 文件和 JavaScript 文件谁先到达,都要先等到 CSS 文件下载完成并生成 CSSOM,然后再执行 JavaScript 脚本,最后再接着继续构建 DOM,构建布局树,绘制页面。

    总结

    文章到这里,深入浅出渲染流程的第一部分就结束了,回顾上面的内容。我们分析了 DOM 和 CSS 的解析、渲染流程,同时还分析了JavaScript和css是如何阻塞HTML渲染的(首页的白屏时间),真心希望大家多看几遍好好消化。大家敬请期待深入浅出渲染流程的第二部分。

你可能感兴趣的:(javascript,面试,渲染)