Published on

性能优化篇(六) : PRPL模式

翻译至: PRPL模式

此系列文章:

性能优化篇(一) : 分包

性能优化篇(二) : 压缩Javascript

性能优化篇(三) : 动态导入

性能优化篇(四) : Prefetch

性能优化篇(五) : Preload

性能优化篇(七) : Tree Shaking

PRPL模式

使应用程序在全球范围内访问可能是一个挑战,我们必须确保应用程序在低端设备和互联网连接较差的地区表现良好。为了确保我们的应用程序可以在困难的条件下尽可能高效地加载,我们可以使用 PRPL 模式。

PRPL 模式侧重于四个主要性能考虑因素:

  • 预加载延迟发现的资源。

  • 尽快渲染初始路由,提升用户体验

  • 在后台预先缓存经常访问的路由资源,以最大程度地减少对服务器的请求量并提供更好的离线体验

  • 延迟加载不经常请求的路线或资源

HTTP1 时代

当我们想要访问一个网站时,首先必须向服务器发出请求才能获取这些资源。入口点指向的文件从服务器返回,通常是我们应用程序的根 HTML 文件。浏览器的 HTML 解析器从服务器接收到数据后就开始解析工作。

如果解析器发现需要更多资源,例如样式表或脚本,则会向服务器发送另一个 HTTP 请求以获取这些资源。

每次都重复请求资源并不是最佳选择,因为我们需要最大限度地减少客户端和服务器之间的往返次数。


长期以来,我们使用 HTTP/1.1 来进行客户端和服务器之间的通信。尽管与 HTTP/1.0 相比,HTTP/1.1 引入了许多改进,例如能够在使用 keep-alive 标头发送新的 HTTP 请求之前保持客户端和服务器之间的 TCP 连接处于活动状态,但仍然存在一些问题。

与HTTP/1.1相比,HTTP/2引入了一些显着的变化,这使得我们更容易优化客户端和服务器之间的消息交换。

HTTP/1.1 在请求和响应中使用换行符分隔的纯文本协议,而 HTTP/2 将请求和响应分割成称为帧的小部分。包含headerbody字段的 HTTP 请求至少分为两个帧:headers帧和data帧。

HTTP/1.1 客户端和服务器之间最多有 6 个 TCP 连接。在通过同一 TCP 连接发送新请求之前,必须先应答之前的请求。如果前一个请求需要很长时间才能解决,则此请求将阻止发送其他请求。这个常见问题称为队头阻塞,可能会增加某些资源的加载时间。


HTTP 2

HTTP/2 使用双向流,这使得可以有一个包含多个双向流的单个 TCP 连接,可以在客户端和服务器之间传输多个请求和响应帧!

一旦服务器收到该特定请求的所有请求帧,它就会重新组装它们并生成响应帧。这些响应帧被发送回客户端,客户端重新组装它们。由于流是双向的,因此我们可以通过同一流发送请求帧和响应帧

HTTP/2 通过在前一个请求应答之前可以在同一个 TCP 连接上发送多个请求来解决队头阻塞问题(单向单车道 —— 双向多车道)。


Server Pushing

HTTP/2 还引入了一种更优化的数据获取方式,称为服务器推送。服务器不必每次都通过发送 HTTP 请求来显式请求资源,而是可以通过“推送”这些资源来自动发送附加资源。

客户端收到额外资源后,资源将存储在浏览器缓存中。当解析入口文件时发现需要后续资源时,浏览器可以快速从缓存中获取资源,而不必向服务器发出HTTP请求!

尽管推送资源减少了接收额外资源的时间,但服务器推送不支持 HTTP 缓存。下次访问该网站时,推送的资源将无法使用,必须再次请求。

为了解决这个问题,PRPL 模式在初始加载后使用服务工作线程来缓存这些资源,以确保客户端不会发出不必要的请求。

作为开发者,我们通常知道哪些资源对于数据获取早期至关重要,而浏览器会尽力推测出。幸运的是,我们也可以通过向关键资源添加 preload 资源提示来帮助浏览器更快找到。

通过告诉浏览器您想要预加载某个资源,相当于在告诉浏览器希望更快地获取它!预加载是优化加载当前路由所需的关键资源时间的好方法。

尽管预加载资源是减少往返次数和优化加载时间的好方法,但推送太多文件可能是有害的。浏览器的缓存是有限的,您可能会通过请求客户端实际不需要的资源来过多的使用了不必要的带宽。


PRPL 模式侧重于优化初始负载。在初始路由完全加载和渲染之前,不会加载其他资源!

我们可以通过将应用程序代码分割成小的、高性能的包来实现这一点。这些Bundle包应该使用户能够仅在需要时加载他们需要的资源,同时还最大化可缓存性!

缓存较大的包可能是一个问题。多个捆绑包可能会共享相同的资源。

浏览器很难识别Bundle包的哪些部分在多个路由之间都存在,因此无法缓存这些资源。缓存资源对于减少服务器与客户端之间的往返次数非常重要!

通过配置浏览器和服务器以支持 HTTP/2 推送并有效地缓存资源,可以轻松模拟通过打包应用动态请求最少资源的好处。对于不支持 HTTP/2 服务器推送的浏览器,我们可以创建一个经过优化的构建,以最大限度地减少往返次数。客户端不必知道它接收的是bundle资源还是非bundle资源:服务器为每个浏览器提供适当的构建。

PRPL 模式通常使用应用程序 shell 作为其主要入口点,这是一个包含大部分应用程序逻辑并在路由之间共享的最小文件!它还包含应用程序的路由器,可以动态请求必要的资源。

PRPL 模式确保在初始路由在用户设备上可见之前不会请求或渲染其他资源。一旦初始路由成功加载,就可以安装server worker,以便在后台获取其他经常访问的路由的资源。

由于这些数据是在后台获取的,因此用户不会遇到任何延迟。如果用户想要导航到 Service Worker 缓存的经常访问的路线,Service Worker 可以快速从缓存中获取所需的资源,而不必向服务器发送请求。

可以动态导入不常访问的路由资源。


参考:

thinking prpl - a progressive web pattern

PRPL Pattern

How to achieve Performance using the PRPL Pattern