【PWA学习与实践】(10)使用Resource Hint提升页面加载性能与体验

《PWA学习与实践》系列文章已整理至 gitbook - PWA学习手册,文字内容已同步至 learning-pwa-ebook。转载请注明作者与出处。

本文是《PWA学习与实践》系列的第十篇文章。也许你还没有听说过或不了解Resource Hint,但是通过本文,你会快速学习到这一件页面加载性能利器。本系列相关demo的代码都可以在github repo中找到。

PWA作为时下最火热的技术概念之一,对提升Web应用的安全、性能和体验有着很大的意义,非常值得我们去了解与学习。对PWA感兴趣的朋友欢迎关注《PWA学习与实践》系列文章。


对之前的文章感兴趣的话,可以从这里找到:

  • 第一篇:2018,开始你的PWA学习之旅
  • 第二篇:10分钟学会使用Manifest,让你的WebApp更“Native”
  • 第三篇:从今天起,让你的WebApp离线可用
  • 第四篇:TroubleShooting: 解决FireBase login验证失败问题
  • 第五篇:与你的用户保持联系: Web Push功能
  • 第六篇:How to Debug? 在chrome中调试你的PWA
  • 第七篇:增强交互:使用Notification API来进行提醒
  • 第八篇:使用Service Worker进行后台数据同步
  • 第九篇:PWA实践中的问题与解决方案

引言

我们知道,在没有缓存的情况下,无论是HTML、javascript还是一些API数据,页面的每一个请求都需要从客户端发起后经由服务端返回。在这种情况下,我们每一次涉及远程请求的交互(打开一个页面、查询列表数据、动态加载js脚本等)都会有网络延迟。如果我们能够预测或指定页面预先进行一些网络操作,例如DNS解析或者预加载资源,那么当我们在之后的操作中涉及到这部分资源时,加载会更迅速,交互也会更加流畅。

当然,目前已经有一些技术手段来帮助我们实现资源的预加载,例如常见的使用XMLHttpRequest来获取资源并进行缓存。然而,这些技术都是应用层面的,并非Web标准,某些需求也无法准确实现。同时,在性能方面也存在着问题。好在目前已有相关的Web标准(Resource Hint)涉及到这一部分,通过它,可以在浏览器原生层面实现这些功能,同时提供性能保证。下面我们来了解一下Resource Hint相关技术。

1. Resource Hint

Resource Hint是一系列相关标准,来告诉浏览器哪些源(origin)下的资源我们的Web App想要获取,哪些资源在之后的操作或浏览时需要被使用,以便让浏览器能够进行一些预先连接或预先加载等操作。Resource Hint有DNS Prefetch、Preconnect、Prefetch和Prerender这四种。

1.1. DNS Prefetch

当我们在注重前端性能优化时,可能会忽略了DNS解析。然而DNS的解析也是有耗时的。在Chrome的Timing Breakdown Phase中,第三阶段就是DNS查询。DNS Prefetch就是帮助我们告知浏览器,某个源下的资源在之后会要被获取,这样浏览器就会(Should)尽早解析它。

Resource Hint主要通过使用link标签。rel属性确定类型,href属性则指定相应的源或资源URL。DNS Prefetch可以像下面这样使用:

1.2. Preconnect

我们知道,建立连接不仅需要DNS查询,还需要进行TCP协议握手,有些还会有TLS/SSL协议,这些都会导致连接的耗时。因此,使用Preconnect可以帮助你告诉浏览器:“我有一些资源会用到某个源,可以帮我预先建立连接。”

根据规范,当你使用Preconnect时,浏览器大致做了如下处理:

  • 首先,解析Preconnect的URL
  • 其次,根据当前link元素中的属性进行cors的设置
  • 默认先将credential设为true;如果cors为Anonymous并且存在跨域,则将credential置为false
  • 最后进行连接

使用Preconnect只需要将rel属性设为preconnect即可:

当然,你也可以设置CORS

需要注意的是,标准并没有硬性规定浏览器一定要(而是SHOULD)完成整个连接过程,浏览器可以视情况完成部分工作。

1.3. Prefetch

你可以把Prefetch理解为资源预获取。一般来说,可以用Prefetch来指定在紧接着之后的操作或浏览中需要使用到的资源,让浏览器提前获取。由于仅仅是提前获取资源,因此浏览器不会对资源进行预处理,并且像CSS样式表、JavaScript脚本这样的资源是不会自动执行并应用于当前文档的。

需要注意的是,和DNS Prefetch、Preconnect使用不太一样的地方是,Prefetch有一个as的可选属性,用来指定获取资源的类型。由于不同的资源类型会具有不同的优先级、CSP、请求头等,因此该属性很重要。下表列出了一些常用资源的as属性值:

资源使用者 写法

浏览器首先会去获取nextpage.js,然后获取并执行current.js,最后,遇到使用nextpage.js资源的script标签时,将已经获取的nextpage.js执行。由于我们会将script标签置于body底部来保证性能,因此可以考虑在head标签中添加这些资源的Preload来加速页面的加载与渲染。

更进一步,我们还可以监听Preload的情况,并触发自定以操作



正如在引言中所提到的,在过去如果我们想预加载一些资源都会用一些应用层面的技术手段,但往往会遇到两个问题:

  • 我们需要先获取资源,然后在适当时执行,但两者并不易于分离
  • 无论哪种技术实现,都会带来一定的性能与体验损伤

Preload(包括前文提到的Prefetch等RHL)给我们带来的价值就是从浏览器层面很好地将资源的加载与执行分离了,并在浏览器层面来保证良好的性能体验。

看到这里,也许你会疑惑,都是会预获取资源,都是资源的获取与执行分离,那么Preload与Prefetch有什么区别呢?

这是它最容易与Prefetch混淆的地方。在标准里有这么一段话解释两者区别:

The application can use the preload keyword to initiate early, high-priority, and non-render-blocking fetch of a CSS resource that can then be applied by the application at appropriate time

与Prefetch相比,Preload会强制浏览器立即获取资源,并且该请求具有较高的优先级(mandatory and high-priority),因此建议对一些当前页面会马上用到资源使用Preload;相对的,Prefetch的资源获取则是可选与较低优先级的,其是否获取完全取决于浏览器的决定,适用于预获取将来可能会用到的资源。

为了节省不必要的带宽消耗,如果Preload的资源在3s内没有被使用,Chrome控制台会出现类似下图的警告。这时你就需要仔细思考,该资源是否有必要Preload了。

更多Preload与Prefetch的细节差异可以看这里 —— Preload, Prefetch And Priorities in Chrome。

3. 写在最后

本文介绍了如何使用Resource Hint(以及Preload)来提升页面加载性能与体验,简单来说:

  • DNS Prefetch 可以帮助我们进行DNS预查询;
  • Preconnect 可以帮助我们进行预连接,例如在一些重定向技术中,可以让浏览器和最终目标源更早建立连接;
  • Prefetch 可以帮助我们预先获取所需资源(并且不用担心该资源会被执行),例如我们可以根据用户行为猜测其下一步操作,然后动态预获取所需资源;
  • Prerender 则会更进一步,不仅获取资源,还会预加载(执行)部分资源,因此如果我们Prerender下一个页面,打开该页面时会让用户感觉非常流畅;
  • Preload 则像是 Prefetch的升级版,会强制立即高优获取资源,非常适合Preload(尽早获取)一些关键渲染路径中的资源。

虽然,大部分PWA相关资料中并不会提及Resource Hint,但是正如我在第一篇文章中提到的

PWA本身其实是一个概念集合,它不是指某一项技术,而是通过一系列的Web技术与Web标准来优化Web App的安全、性能和体验。

Resource Hint显然符合这一点。

我们不应该将PWA局限在Service Worker离线缓存、提醒通知这些常见的PWA内容中,希望读者也能开阔思维,理解PWA背后的概念与思想。因此,在后续文章中我也会介绍前端存储(sessionStorage/localStorage/indexDB)、HTTP/2.0以及PWA进展等相关内容。

在下一篇里,我们会一起来学习Google开源的PWA离线工具集 —— workbox。通过workbox,我们可以学习各类离线策略,并且了解一些生产环境中需要考虑的问题。部分开源PWA解决方案也是基于workbox进行封装的。

《PWA学习与实践》系列

  • 第一篇:2018,开始你的PWA学习之旅
  • 第二篇:10分钟学会使用Manifest,让你的WebApp更“Native”
  • 第三篇:从今天起,让你的WebApp离线可用
  • 第四篇:TroubleShooting: 解决FireBase login验证失败问题
  • 第五篇:与你的用户保持联系: Web Push功能
  • 第六篇:How to Debug? 在chrome中调试你的PWA
  • 第七篇:增强交互:使用Notification API来进行提醒
  • 第八篇:使用Service Worker进行后台数据同步
  • 第九篇:PWA实践中的问题与解决方案
  • 第十篇:Resource Hint - 提升页面加载性能与体验(本文)
  • 第十一篇:从PWA离线工具集workbox中学习各类离线策略(写作中…)

参考资料

  • Resource Hints W3C Working Draft 15 January 2018
  • Preload W3C Candidate Recommendation 26 October 2017
  • Preload, Prefetch And Priorities in Chrome
  • Web Linking
  • Page Visibility Level 2 W3C Proposed Recommendation 17 October 2017
  • CORS settings attributes
  • Content Security Policy Level 3 W3C Working Draft, 13 September 2016

你可能感兴趣的:(pwa,frontend)