奇技指南 今天给大家介绍一个性能优化利器:Preload。 本文作者是来自奇舞团的前端工程师黄小璐,同时是W3C性能工作组成员。 背景 有时候为了提高网页初始加载的性能,我们会选择延迟一部分资源的加载和执行。 另一种情况是我们想要尽早加载资源,但是要等到合适的时机再执行。时机的影响因素包括依赖关系、执行条件、执行顺序等。 通常的做法是: 有没有办法既提前加载资源,又能解耦加载和执行呢?这时候就轮到preload大显身手啦。 什么是Preload preload是一个预加载关键字。它显式地向浏览器声明一个需要提前加载的资源。使用方式如下: 当浏览器“看”到这样的声明后,就会以一定的优先级在后台加载资源。加载完的资源放在HTTP缓存中。而等到要真正执行时,再按照正常方式用标签或者代码加载,即可从HTTP缓存取出资源。 使用Preload加载资源的方式有以下几个特点: 大家可能会问:Preload跟其他提前加载资源以及加载和执行分离的方案有什么区别? 好的,满足你们的好奇心: vs. 预测解析 浏览器很聪明,它可以在解析 HTML 时收集外链资源。并将它们添加到一个列表,在后台并行下载。预测解析也实现了提前加载以及加载和执行分离。如图所示: 那么它跟Preload的区别是什么? vs. async async 脚本是一加载完就立即执行,因此会阻塞window的onload事件。而且目前async仅限于脚本资源。 Preload可以实现async一样的异步加载功能。且不局限于脚本。比如以下代码实现了加载完CSS文件立即作用到网页的功能: <link rel="preload" href="style.css" as="style" onload="this.rel='stylesheet'">
注:如果页面存在同步阻塞脚本,等脚本执行完后,样式才会作用到网页。这样是因为Preload的资源不会阻塞window的onload事件。
vs. defer defer实现了资源的加载和执行分离,并且它能保证 defer的资源按照在HTML里的出现顺序执行。跟async一样,目前也只能作用于脚本资源。 Preload则适用多种资源类型。Preload的资源也能像defer的资源一样延迟执行并保证执行顺序。 vs. Sever Push HTTP/2的Server Push也实现了资源的提前加载以及加载执行分离。不过Server Push节省了一个网络来回。我们可以结合Server Push优化Preload,比如服务器识别到文档里的Preload的资源就主动推送Preload的资源。 如果不希望服务器推送,则可以增加nopush属性: Link: </app/style.css>; rel=preload; as=style; nopush
另外Server Push只能推送同域资源。而Preload则可以支持跨域资源。 何时使用Preload 任何你想要先加载后执行,或者想要提高页面渲染性能的场景都可以使用Preload。 典型用例: 在单页应用中,提前加载路由文件,提高切换路由时的渲染速度。现在大型的单页应用通常会异步加载路由文件。当用户切换路由时再异步加载相应的模块存在性能问题。可以用Preload提前加载,提升性能。 提前加载字体文件。由于字体文件必须等到CSSOM构建完成并且作用到页面元素了才会开始加载,会导致页面字体样式闪动(FOUT,Flash of Unstyled Text)。所以要用Preload显式告诉浏览器提前加载。假如字体文件在CSS生效之前下载完成,则可以完全消灭FOUT。
浏览器兼容性 Preload的兼容性如下: 截至本文写作时,在PC上实现了Preload的浏览器包括: Chrome 50+,Saferi 11.1+ 。Edge 17+支持HTML 方式,不支持HTTP header方式。移动端:iOS Safari 11.4+,Android Chrome 67 不支持Preload的浏览器会自动忽略它,并采用普通的加载方式。因此可以将此功能作为一种渐进增强方式用到我们的网页应用中。 鸣谢 何文力和李松峰对文章的内容和细节提出了宝贵的修订意见,感谢! 参考链接 https://www.w3.org/TR/preload/ https://developer.mozilla.org/zh-CN/docs/Web/HTML/Preloading_content https://www.jianshu.com/p/24ffa6d45087 https://yoavweiss.github.io/link_htmlspecial_16 https://www.w3cplus.com/javascript/building-the-dom-faster-speculative-parsing-async-defer-and-preload.html
界世的你当不 只作你的肩膀 无
|