浏览器预加载器如何使页面加载更快
2013年10月22 日
预加载器(也称为推测式或预先预分析器)可能是浏览器性能的最大改进。
在实施过程中,Mozilla报告说,加载时间有19%的改善,而对Alexa来说,前两千个站点的测试发现,Google发现约有20%的改进。
这不是一个新的浏览器功能,但有些似乎认为它只是Chrome,而其他人则认为这是“最具破坏性”的性能提升“曾经有过”!
那么预装载机是什么,它如何提高性能?
浏览器如何加载网页
网页充满依赖关系 - 页面无法在相关CSS下载之前开始呈现,然后遇到脚本时,HTML解析器将暂停,直到脚本执行(当然如果脚本是外部的,那么它也需要被下载) )。
让我们考虑浏览器如何加载页面:
-
首先,HTML被下载,浏览器开始解析它。它找到一个外部CSS资源的引用,并触发下载它的请求。
-
浏览器可以在CSS正在下载时进行解析HTML,但是它会发现具有外部URL的脚本标记,现在(除非脚本有
async
或defer
属性),它必须等到脚本下载并执行。 -
一旦脚本下载并执行,浏览器可以继续解析HTML,当它发现非阻塞资源,如图像,它会请求它们并进行解析,但是当它找到一个脚本时,它必须停止并等待该脚本被检索并执行。
虽然浏览器能够并行地进行多个请求,但是通常这样的行为往往不会与脚本并行地下载任何资源。
这是浏览器用来表现和使用史蒂夫· 波斯的Curzillion的方式,我们可以创建一个在IE7中演示的测试页面。
该测试页有两种样式,然后在头两个脚本,然后在体内,它有两个图片,脚本,最后另一幅图像。
瀑布使得在下载脚本时可以轻松看到并行下载停止。
Cuzillion瀑布在IE7中生成测试页面
如果浏览器仍然这样工作,那么每次遇到脚本时,页面的加载速度会更慢,浏览器需要等待脚本下载和执行才能发现更多的资源。
预加载器如何提高网络利用率
Internet Explorer,WebKit和Mozilla在2008年都实现了预加载器,作为在等待脚本下载和执行时克服低网络利用率的一种方式。
当浏览器在脚本上被阻止时,第二个轻量级解析器扫描其余的标记,寻找其他资源,例如还需要检索的样式表,脚本,图像等。
然后,预加载器在后台开始检索这些资源,目的是在主HTML解析器到达它们之前,它们可能已经被下载,因此在页面后面减少了阻塞。
(当然如果资源已经在缓存中,那么浏览器就不需要下载了)
使用IE8重复以前的测试显示其他资源现在与脚本并行下载,为此测试案例提供了巨大的性能提升:7s vs 14s。
Cuzillion瀑布在IE8中生成测试页
预装载程序行为因浏览器而异,仍然是实验领域,有些浏览器似乎具有天真的实现,它们按照发现的顺序下载资源,但其他浏览器会优先下载,例如Safari给出不适用于当前的视口是一个低优先级,Chrome调度脚本(甚至是页面底部的脚本),其优先级高于页面上的大多数图像。
优先级机制没有很好的记录(您可以阅读某些浏览器的来源!),但如果您想更好地了解自己可以做什么,詹姆斯·西蒙森写了一些关于他们在Chrome中尝试的方法的优秀笔记。
预装载机
预加载器从标记中提取URL,并且不会/不能执行javascript,因此使用javascript插入的任何URL都不可见,并且这些资源的下载将被延迟,直到HTML解析器发现并执行加载它们的JavaScript。
有些情况下,使用javascript插入资源也可以跳过一些预装载。
我在Stack Overflow中遇到了一个答案,建议使用JavaScript来根据浏览器宽度将链接插入移动或桌面样式表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
有几个原因,我不会使用这种方法,但即使这个简单的例子足以让IE9的预加载程序跳闸 - 注意图像如何抓住所有的连接,并且CSS被延迟,直到其中一个图像完成并且连接变为可用。
测试页面加载在IE9中
一些响应式图像方法使用后备图像,并且预加载器通常会在JavaScript之前启动后退图像下载,以选择适当的图像,从而导致额外的下载。
影响预装载机
目前我们有限的方式可以影响预装载程序的优先级(使用javascript隐藏资源是一个),但W3C资源优先级规范提出了两个属性来帮助表明我们的意图。
lazyload
:除非没有标记为lazyload的其他资源已经开始下载,否则不应下载资源
postpone
:资源不能下载,直到用户可见,即在视口内,显示不是没有。
虽然我不确定polyfill是多么容易,也许延期可能会实现一个简单的实现响应图像的方法?
预加载与预取
预取是一种向浏览器提示将来肯定会或可能使用的资源的一种方式,一些提示适用于当前页面,其他提示适用于将来的页面。
在最简单的级别,我们可以告诉浏览器解决另一个主机名的DNS,我们稍后将在页面上访问:
1 | |
Chrome还允许我们暗示我们将在当前页面中稍后使用另一种资源,因此应将其下载为高优先级:
1 | |
(Chromium的源代码表明,它实际上被下载到比样式表/脚本和字体更低的优先级,但是等同于或高于图像的优先级)
还有两种链接类型,允许我们推测提示下一步的内容,并将以比当前页面上的资源更低的优先级进行下载。
预取可能在下一页的单个资源:
1 | |
在后台选项卡中预取并呈现整个页面:
1 | |
Ilya Grigorik的Preconnect,preetch,prerender ...从WebPerfDays 谈话纽约是一个很好的开始,如果你想了解更多关于预取。
概要
预加载器不是新的,它提供了显着的性能提升,作为作者,我们不需要做任何特别的事情来利用它。
它被广泛实现 - 我测试了以下浏览器以确认他们有一个预加载器:
- IE8 / 9/10
- Firefox
- Chrome(包括Android)
- Safari(inc iOS)
- Android 2.2.2 / 2.3(2.2.2测试2014年5月18日)
Bruce Lawson也证实了Opera Mini使用了Presto引擎,它具有一个预装载器。
资源优先事项(也许<link rel=subresource...
)将给我们一些方法来表明我们的优先事项。
如果你发现任何打字错误,或有问题,并添加他们在评论中,我会尽力解决和回答。