第二章 构建 PWA 的第一步

2.1 建立在现有基础上

使用 Lighthouse 对现有的 Web 应用进行性能分析和信息审核。

2.2 构建 PWA 的前端架构方式

2.2.1 应用外壳架构

Service Worker 可以缓存网站的 UI 外壳,以便用户重复访问。

UI 外壳是指用户界面所必须的最小化的 HTML、CSS 和 JavaScript。可能回事类似网站头部、底部和导航这样没有任何动态内容的部分。

2.2.2 性能优势

对于首次访问的用户,由于是首次获取这些资源,所以该网站需要更长的下载时间。一旦所有的资源下载完成,首次访问的用户大约在 4s 后就能够与网站进行完整的交互。

对于再次访问的用户,此时 Service Worker 服务已经安装并运行,即使此时动态内容还没有从服务器返回,UI 外壳也会首先加载完成。此刻可以向用户展示一些有意义的东西,比如,通知他们目前处于离线状态或为其提供已缓存的内容。

2.2.3 应用外壳架构实战

当用户首次访问网站时,Service Worker 会开始下载并自行安装。在安装阶段,可以进入这个事件并准备缓存 UI 外壳所需的所有资源,即基础的 HTML 页面和任何可能需要的 CSS 或 JavaScript。

对于不支持 Service Worker 的浏览器,此法依然有效,只是它们没有缓存 UI 外壳的资源,不会获得额外的加速性能。

把动态内容加载到网站中,网站会正常运行。当进入这些请求的 fetch 事件时,可以决定是否要缓存它们。

2.3 逐步剖析现有的 PWA

Twitter Lite 为例。

2.3.1 前端架构

在底层,Twitter Lite 是使用应用外壳架构构建的。此外还针对使用响应式网页设计的不同屏幕尺寸进行了优化。

2.3.2 缓存

Service Worker 能够拦截 HTTP 请求和响应,并根据需要调整和缓存它们。Twitter Lite 使用了一个叫做 Service Worker Toolbox 的库,包含了一些使用 Service Worker 进行尝试并验证过的缓存技术。Twitter Lite 使用这项技术来缓存它们的 emoji 表情。

1
2
3
4
5
6
7
8
9
10
11
toolbox.router.get('/emoji/v2/svg/:icon', function(event) { // 拦截路径为 '/emoji/v2/svg/:icon' 的任意请求
return caches.open('twemoji').then(function(response) { // 打开一个名为 twemoji 的已存在的缓存
return response.match(event.request).then(function(response) { // 检查当前请求是否匹配缓存中的内容
return response || fetch(event.request) // 如果匹配,则立即返回缓存内容;否则,继续按照一般方式运行
})
}).catch(function() {
return fetch(event.request) // 如果在打开缓存时出现问题,继续按照一般方式运行
})
}, {
origin: /abs.*\.twimg\.com$/ // 只检查 twimg.com 域名下的资源
})

上述代码中,寻找 URL 匹配 /emoji/v2/svg/ 并且来自 *.twimg.com 站点的任何请求。一旦拦截到匹配此路由规则的任意 HTTP 请求,就会把它们存储在名为 twemoji 的缓存之中。等下次用户再次发起匹配此路由的请求时,呈现给用户的将是缓存的结果。

2.3.3 离线浏览

Service Worker 缓存可将网站资源保存到用户的设备上。基于这点可以构建离线页面。如 Twitter Lite 在没有网络连接的情况下会展现一个自定义的离线页面。

2.3.4 观感

1
<link rel="manifest" href="/manifest.json">

这个文件只是简单的 JSON 文件,遵循 Web App Manifest 规范。它提供 Web 应用的信息,比如名称、作者、图标和描述。它使浏览器能够将 Web 应用安装到设备的主屏幕上,以便为用户提供更快捷的访问和更丰富的体验。通过在清单文件中设置品牌颜色,可以自定义浏览器自动显示的启动画面。还允许你自定义浏览器的地址栏以匹配你的品牌颜色。

2.3.5 最终产品

Twitter Lite 的特点:

  • 响应式的——适应较小的屏幕尺寸。
  • 连接无关的——由于 Service Worker 缓存,它可以离线工作。
  • 应用式的交互——它使用应用外壳架构进行构建。
  • 始终保持最新——由于 Service Worker 的更新过程,它会不断更新。
  • 安全的——它通过 HTTPS 进行工作。
  • 可发现的——搜索引擎可以找到它。
  • 可安装的——使用清单文件可以进行安装。
  • 可链接的——可以通过 URL 来轻松分享。