从输入url到浏览器显示页面,发生了什么?(浏览器渲染篇)

我们今天来了解一下浏览器工作原理,它是由呈现引擎(也就是各位道友常说的内核)来完成的。我们今天主要借助 webkit 来看一下。

渲染流程

呈现引擎一开始会从网络层获取请求文档的内容,然后开始进行下面的这个流程:

渲染引擎流程-webkit

我们可以看出如下几个点:

  1. 浏览器解析HTML/CSS:

    解析 HTML ,生成 DOM Tree。
    解析 CSS ,生成 Style Rules(样式规则)。
    Javascript 的解析主要是通过 JavaScript 解释器来进行的,不是呈现引擎的事。它主要是通过 DOM API 和 CSSOM API 来分别操作 DOM Tree 和 Style Rules。

  2. 解析完成后,浏览器引擎会通过 DOM Tree 和 Style Rules 来构造 Rendering Tree。

    当文档被解析并且添加 DOM 节点时,在 DOM 节点上调用称为 attach 的方法来创建渲染器。

    Rendering Tree 渲染树并不等同于 DOM Tree,因为 attach 方法会计算样式信息,一些像 headdisplay:none 的元素就没必要放在渲染树中了。

    WebKit 支持的每一个 CSS 属性都可以通过 RenderStyles (所有的样式信息都存储在上面)查询。如果 DOM 节点创建了一个渲染器,那么它使用渲染器上的 setStyle 方法将该样式信息连接到该渲染器。而火狐是通过生成 规则树 和 样式上下文树 ,来进行与 DOM Tree 的匹配。最后生成 Render Tree。

    DOM Tree 和 Render Tree

  3. 计算每个 frame (元素) 的位置,进行 layout 。

  4. 呈现引擎遍历呈现树,由用户界面后端层将每个节点绘制出来。绘制的顺序是:

    • 背景颜色
    • 背景图片
    • 边框
    • 子代
    • 轮廓

总结一下工作原理:HTML/CSS parse —> Render Tree —> layout —> paint 。

需要着重指出的是,这是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它不必等到整个 HTML 文档解析完毕,就会开始构建呈现树和设置布局。在解析外联脚本的同时,呈现引擎会将已解析的页面内容显示出来。

DOM 阻塞

JS 阻塞文档解析

当遇到 <script> 标签时,会立即解析并执行脚本。如果脚本是外部的,则会立即停止解析,直到脚本下载下来之后继续解析脚本。这样做是有原因的,因为 javascript 可能会有诸如 document.write 的操作,这样的话,后续所有资源的加载都是无意义的。

JS 有 defer 属性, es5还新增了一个 async 属性。他们都可以实现异步加载,不会阻塞文档解析。他们的区别就是 async 下载完了之后会立即执行,而 defer 是在遇到 </html> 才会执行(先于 DOMContentLoaded 事件)。

script 正常加载与 defer、async 的区别

还有一个同样可以实现异步加载,通过 DOM 动态添加。它的执行顺序排在 defer 之后,DOMContentLoaded 事件之前。

根据上面的特性我们可以发掘出的优化js的方法有:

  • 合理使用 defer 和 async 或者 DOM 动态添加
  • 合并 js 文件,或者适当的内嵌,减少请求–>减少请求时间–>减少阻塞时间
  • Minify Javascript

CSS 阻塞 JS

如果 js 去请求 css 的信息,这个时候 css 还没加载完毕,就会导致取到的信息错误。为了防止这一点,css 会阻塞 js 的解析。谷歌做了优化,只有脚本去访问的样式会受到尚未加载解析的 css 影响时,才会禁止此脚本。

我们可以通过 media query 来进行优化。比如:

<link href=”something.css” rel=”stylesheet” media=”(min-width: 750px)”

这样如果小于 750px ,则不会加载该 css 。

预解析

在执行脚本时,其他线程会解析剩余文档,找出并提前下载好其他资源,但是不执行。这不会更新 DOM 树,这项工作会留给主解析器来完成。

因为浏览器是有并行下载限制的,所以我们能够尽可能的减少图片等的体积,还是需要尽量减小。

总结

  1. 发送 HTTP 请求,获取 HTML
  2. 解析 HTML ,构建 DOM树
  3. 发送 HTTP 请求,获取 CSS 和 JS 和 IMG
  4. 解析 CSS 创建 RenderStyles,解析执行 JS
  5. 基于 viewport 生成布局
  6. 绘制页面
  7. 重复 2 - 6

热评文章