图解Chrome:HTML/CSS/JS是如何在浏览器中,渲染成你看到的页面?

作者:CQITer小编 时间:2018-10-23 09:08

字号

Chrome 算是程序员的标配了,从全球的市场份额来看,它在全球市场的份额已经超过 60%。

Chrome 10 周年之际,官方发布了一个系列文章,用图解的方式,很清晰的讲解了现代浏览器的运行原理。

渲染器进程的内部工作原理

本系列分为 4 个部分,主要讲解关于现代浏览器的运行原理,本文为该系列的第 3 篇。在之前的文章中,我们介绍了多进程架构和导航的完整流程,而在这篇文章中,我们将探究在渲染器进程的内部,到底发生了什么。

渲染器进程涉及到 Web 性能相关的多个方面,由于渲染器进程中处理了很多的逻辑,不是一篇文章可以全面讲解的,因此本文仅作为一个概述。如果你有兴趣深入研究,可以在《Why Performance Matters》这篇文章里找到更多的资料。

渲染器进程处理Web内容

所有选项卡内发生的逻辑,都由渲染器进程负责。在渲染器进程中,主线程处理了服务器发送给用户的大部分代码。如果你使用到 Web Workder 或者Service Worker,那 JavaScript 中的这部分代码,将由工作线程处理。Compositor(合成器) 和 Raster(光栅) 线程也在渲染器内运行,从而实现高效、流畅的渲染页面。

图解Chrome:HTML/CSS/JS是如何在浏览器中,渲染成你看到的页面?

渲染器进程的核心工作是将 HTML,CSS 和 JavaScript 转换为用户可以与之交互的网页。

上图中,描述了具有主线程、工作线程、Compositor 线程、Raster 线程的渲染器进程,以及他们之间的关系。

解析

构建 DOM

当渲染器进程收到一个导航请求,并开始接收 HTML 数据,主线程将开始处理文本字符串(HTML),将其解析成 DOM(Document Object Model)。

DOM 是 Web 页面的内部的逻辑树文档结构,Web 开发人员可以通过 JavaScript 脚本与之交互数据,以及通过标准 API 来操作 DOM 节点。

将 HTML 文档解析成 DOM 是完全依照于 HTML 协议。并且在 HTML 协议中,浏览器不会对错误的 HTML 进行错误提示。例如,缺少结束的 </p> 标签时,这依然是一个有效的 HTML。类似 Hi! <b>I'm <i>Chrome</b>!</i> 中,b 标签在 i 标签之前关闭这样的错误,会被 HTML 理解为 Hi! <b>I'm <i>Chrome</i></b><i>!</i>。这是因为 HTML 规范的主要原则是优雅的处理这些错误,而不是严格检查。

如果你对这些规范感到好奇,可以阅读 HTML 规范中的 “解析器中的错误处理和奇怪案例介绍” 部分。

解析器中的错误处理和奇怪案例介绍:

https://html.spec.whatwg.org/multipage/parsing.html#an-introduction-to-error-handling-and-strange-cases-in-the-parser

子资源加载

一个完整的 Web 站点通常会包含图片、CSS 和 JS 等外部资源,这些文件都需要从网络或者本地缓存中加载。主线程可以在解析构建 DOM 的时候,将他们逐个请求,但是为了加快速度,会同时使用 “预加载扫描(Preload Scanner)”。

如果 “预加载扫描” 发现有类似 <img> 或 <link> 这样的标签时,会由 HTML 解析器对该资源生成一个 Tokens,然后在浏览器进程中,通过网络或者本地缓存来加载资源。

图解Chrome:HTML/CSS/JS是如何在浏览器中,渲染成你看到的页面?

上图描述了,主线程解析 HTML 并构建 DOM 树的过程。

JS 可以阻止解析

当 HTML 解析器遇到 <script> 标签的时候,它会暂停解析 HTML 文档,然后对这个 JS 脚本进行加载、解析和执行。

这么设计的原因,是因为 JS 可以使用类似 document.write() 方法来改变 DOM 的结构。这就是 HTML 解析器在重新解析 HTML 之前,必须等待 JS 脚本执行的原因。

如果你对 JS 执行中发生的事情细节有兴趣,V8 团队有一篇文章深入的对此进行了讲解,有兴趣可以看看。

V8 团队深入研究:

https://mathiasbynens.be/notes/shapes-ics

提示浏览器如何加载资源

HTML 遇到 JS 脚本则暂停对 HTML 的解析,这并不是绝对的。

Web 开发人员可以通过多种方式的配置,告知浏览器如何更优雅的加载资源。如果你的 JS 脚本中,没有使用到类似 document.write() 这样的方法,你可以在 script 标签中添加 async 或 defer 标记,然后浏览器会异步加载和运行此 JS 脚本,不会阻断解析。如果需要,也可以使用 JavaScript Modules,还可以通过 <link rel="preload"> 标签向浏览器明确标记此为重要的资源,将在页面加载完成之后被立刻使用,对于这类资源,它会在页面加载生命周期的早期,被优先加载。

样式渲染(Style)

仅仅解析成 DOM,还不足以完成页面渲染,因为还可以通过在 CSS 中,设置元素的样式来丰富渲染效果。

主线程将解析 CSS,并将效果渲染到指定的 DOM 节点上,关于 CSS 选择器如何定位到指定的 DOM 节点,可以通过 DevTools 来查看相关信息。

图解Chrome:HTML/CSS/JS是如何在浏览器中,渲染成你看到的页面?

上图中,主线程解析 CSS 并添加渲染样式。

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
关键词 >>Chrome HTML CSS
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接