大数跨境
0
0

聊一聊浏览器资源加载

聊一聊浏览器资源加载 点融黑帮
2015-10-23
1
导读:大鱼告诉你如何优化浏览器加载资源。

导语:

优化浏览器资源加载是为了让浏览器尽可能快地绘制网页:较快的页面呈现速度可以提高互动度、增加网页浏览量并提高转化率。因此,我们希望通过优化要加载的资源和加载顺序,尽可能减少访问者注视空白屏幕的时间




1浏览器资源解析

我们从最简单的情况开始,一个HTML页面,只包含了一些文字和一张图片,浏览器会如何处理呢?


- 转换: 浏览器读取HTML的原生字节并将它们转换为有意义的字符(例如UTF-8)。
- 符号化(Tokenizing):浏览器从字符串中把它认识并有特殊意义的字符提取出来,例如“<html>”, “<p>”。这些符号都有预定的意义和规则。

- 词法分析:提取出来的字符被转换为对象,并添加相应的属性和规则。

- DOM的构建:最后,HTML根据标签的定义和组织形式,定义对象的关联关系,例如HTML对象包含了Body对象,Body对象包含了p对象,最终将这些关联关系保存在一个树形结构中。


DOM处理完毕,浏览器此时是否马上可以在屏幕上开始呈现呢?还不行,DOM只是捕获了文档标记的属性及关系,但是并没有提供这些标记长什么样子的信息。这是CSSOM负责的内容。我们在HTML页面加入一个CSS文件的引用,定义一些基本的样式。


与HTML一样,浏览器会并把这个CSS文件转换为它认识的内容,因此会重复与上一步非常相似的过程。CSS字节转换为字符,然后转换为符号和节点,最后链接进树状结构上,即所谓的CSS对象模型。


现在我们已经根据输入的HTML与CSS构建了DOM树及CSSOM树,一个描述文档内容,另一个描述应用于文档的样式规则。浏览器接下来便要将DOM树与CSSOM树融合成渲染树。给每个DOM节点找到相应匹配的CSSOM规则,计算样式。有了渲染树,我们就能进入布局阶段。布局阶段做的主要工作就是计算出文档节点在设备视图中的准确位置与尺寸,最终输出一个盒模型。我们知道了哪些节点可见,它们的计算的样式以及几何信息,我们终于可以将这些信息传递给最后一个阶段,即把渲染树中的每个节点转换为屏幕上的实际像素, 这一步通常称为绘制或者栅格化。


一旦完成上述步骤,我们的页面像在视窗中可见了!




2浏览器资源依赖

在前面的内容中,我们看到我们同时需要DOM和CSSOM来构造渲染树,这意味着HTML和CSS都是阻塞渲染的关键型资源。HTML容易理解,没有DOM,我们就没有任何可渲染的内容,但是CSS的必要性就没那么明显。如果我们在CSS不阻塞的情况下尝试渲染一个页面会怎样?




没错,你会看到一块儿“大白”。它说明了为什么要在CSS可用之前阻塞渲染——没有CSS的页面基本不可用。实际上,右侧的情况通常称为内容样式短暂失效(Flash of Unstyled Content)。因此,在同时拥有DOM和CSSOM前,浏览器会阻塞渲染。


这时如果我们在页面中引入Javascript呢?情况会变得更为复杂。Javascript允许我们修改页面上的种种:我们可以向DOM树添加或移除元素来修改页面内容,我们可以处理用户输入,等等。正因为它可以影响DOM树的生成,我们的脚本在文档的哪儿插入,即在哪儿执行。HTML解析器遇到一个script标签,它会暂停构建DOM,并移交控制权给JavaScript引擎;等JavaScript引擎执行完毕,浏览器从中断的地方恢复 DOM构建。因此,脚本会阻塞DOM构建,也就延缓了首次渲染。


另外Javascript还可以读取、修改CSSOM,从而使我们面临着一个竞态,如果浏览器尚未完成CSSOM下载与构建,而我们就想运行我们的脚本,会怎样?答案很简单:浏览器会延迟脚本执行,直到完成CSSOM下载与构建,而在我们等待时,DOM构建同样被阻塞。如果是外部的JavaScript,那么情况中会更糕,浏览器必须暂停,然后等待脚本从磁盘、缓存或远程服务器中取回,这就又可能给我们的关键渲染路径增加了显著延迟。



3分析关键呈现路径

我们了解了不同浏览器资源之间的依存关系,便可以确定哪些资源是“重要资源”, 找出在网页中添加这些资源的最佳路径,从而让浏览器最快地获得关键性资源,呈现页面,减少用户的等待时间。我们将这条路径称为关键呈现路径。


首先定义一下描述关键呈现路径的词汇:

- 关键资源:可能阻止网页首次呈现的资源。

- 关键路径长度:即往返过程数量,或提取所有关键资源所需的总时间。

- 关键字节:实现网页首次呈现所需的总字节数,是所有关键资源的传输文件大小总和。


以一个简单的HTML为例,要呈现此网页,浏览器必须初始化请求、等待HTML文档准备就绪、对其进行解析、构建DOM,最后使其呈现在屏幕上:




它包含一项关键资源(HTML文档),关键路径长度也与 1 个网络往返过程(假设文件较小)相等,而且总的关键字节数正好是 HTML 文档本身的传输大小。


现在,我们看一下带有外部CSS文件的同一网页:




我们需要一个网络往返过程来提取 HTML 文档,然后检索到的标记告知我们还需要 CSS文件:这意味着,浏览器必须返回服务器并获取CSS,然后才能在屏幕上呈现网页。因此,该网页最少需要两个往返过程才能显示。(CSS文件可能需要多个往返过程,因此重点在“最少”)。


我们将 “HTML+CSS”的关键路径特征描述一下:

- 2 种关键资源

- 2 个或更多往返过程的最短关键路径长度

- 9 KB 的关键字节


我们再向组合中添加一个额外的JavaScrip文件,如上所述,这是一种解析器阻止(即关键)资源。更糟的是,为了执行JavaScript文件,我们还必须阻止并等待CSSOM,在style.css下载和CSSOM构建完成之前,浏览器将会暂停。




如果我们查看该网页的“网络瀑布流”,就会发现 CSS 和 JavaScript 请求几乎会在同一时间初始化:浏览器获取 HTML,发现这两种资源并初始化这两个请求。因此,上述网页具有以下关键路径特征:

- 3 种关键资源

- 2 个或更多往返过程的最短关键路径长度

- 11 KB 的关键字节


现在,我们拥有三种关键资源,关键字节总量最多为 11 KB,但是我们的关键路径长度仍然是两个往返过程,因为我们可以同时传输CSS和JavaScript。


默认情况下,所有 JavaScript 均会阻塞解析器,因为浏览器不知道脚本想在页面上做什么,因此它必须假定最糟的状况并阻塞解析器。但是,如果我们能够告知浏览器说,脚本无需在文档中引用它的确切位置被执行呢?如此一来,浏览器会继续构建 DOM,并在脚本准备就绪后(比如,从缓存或远程服务器中加载完文件)执行脚本。我们向脚本代码中添加async属性,便可以取消对解析器的阻止:




对脚本进行异步编程具有以下几项优势:

- 脚本再也不会阻止解析器,也不再是关键呈现路径的组成部分

- 因为没有其他关键脚本,CSS 也不需要阻止domContentLoaded事件

- domContentLoaded事件触发得越早,其他应用逻辑开始执行的时间就越早


因此,我们经过优化的网页恢复到了具有两种关键资源(HTML和CSS)、具有两个往返过程的最短关键路径长度和9KB的关键字节总量。



4优化关键呈现路径

总结一下,为了尽快完成首次呈现,我们需要优化下列三种变量:

- 尽量减少关键资源数量。

- 尽量减少关键字节数。

- 尽量缩短关键路径的长度。


关键资源是任何可能阻止网页首次呈现的资源。网页上的关键资源越少,浏览器在屏幕上显示内容时必须完成的工作量就越少,对CPU和其他资源的占用也就越少。


同样,浏览器必须下载的关键字节越少,那么它处理内容并使其呈现在屏幕上的速度就越快。要减少字节数,可以减少资源数量(删除相应资源或者将其设为非关键资源),同时还可压缩和优化各个资源,以尽量降低传输量。


最终,关键路径长度是网页所需的所有关键资源与其字节大小之间的依赖函数:有些资源只有在上一个资源处理完毕后才能开始下载,并且资源越大,下载所需的往返次数就越多。




本文作者:大鱼,前端的资深软件开发工程师。


随着点融网新一轮融资,点融网即将开始大规模的扩张,需要各种优秀人才的加入,如果你觉得自己够优秀,欢迎加入我们!获取更多职位信息,请关注点融黑帮。

【声明】内容源于网络
0
0
点融黑帮
点融黑帮——一个充满激情和梦想的技术团队,吸引了来自金融及信息科技领域的顶尖人才。我们正在用技术创新改变传统金融。
内容 374
粉丝 0
点融黑帮 点融黑帮——一个充满激情和梦想的技术团队,吸引了来自金融及信息科技领域的顶尖人才。我们正在用技术创新改变传统金融。
总阅读7
粉丝0
内容374