了解 ZDF 如何利用离线支持、可安装性和深色模式等现代功能打造渐进式 Web 应用 (PWA)。
在广播公司 ZDF 考虑重新设计其前端技术栈时,他们决定仔细研究其在线播放网站 ZDFmediathek 的渐进式 Web 应用。开发机构 Cellular 接受了挑战,致力于打造与 ZDF 平台专用 iOS 和 Android 应用不相上下的基于网络的体验。PWA 提供可安装性、离线视频播放、过渡动画和深色模式。
添加 Service Worker
离线支持是 PWA 的一个主要功能。对于 ZDF,大部分繁重工作都是由 Workbox 完成的。Workbox 是一组库和节点模块,可轻松支持不同的缓存策略。ZDF PWA 使用 TypeScript 和 React 构建,因此它使用已内置到 create-react-app 的 Workbox 库来预缓存静态资源。这样,应用就可以专注于使动态内容(在本示例中是视频及其元数据)可供离线使用。
基本思路非常简单:提取视频并将其作为 blob 存储在 IndexedDB 中。然后在播放过程中监听在线/离线事件,并在设备离线时切换到已下载的版本。
不幸的是,情况变得有点复杂。其中一项项目要求是使用不提供任何离线支持的官方 ZDF 网页播放器。播放器将内容 ID 作为输入内容,与 ZDF API 通信,然后播放关联的视频。
这正是网络最强大的功能之一:Service Worker。
Service Worker 可以拦截玩家执行的各种请求,并使用 IndexedDB 中的数据进行响应。这样可以透明地添加离线功能,而不必更改玩家的一行代码。
由于离线视频往往非常大,因此一个重要的问题是,设备上实际可以存储多少个视频。借助 StorageManager API,应用可以估算可用空间,并在空间不足时通知用户,甚至在开始下载之前通知用户。遗憾的是,Safari 不在实现此 API 的浏览器列表中,在撰写本文时,有关其他浏览器如何应用配额的最新信息并不多。因此,该团队编写了一个小型实用程序,用于测试各种设备的行为。到目前为止,已经有一篇内容详尽的文章汇总了所有细节。
添加自定义安装提示
ZDF PWA 提供自定义的应用内安装流程,会在用户想要下载第一个视频后立即提示用户安装该应用。这是显示安装提示的理想时机,因为用户已表达了使用离线应用的明确意图。
![自定义安装邀请。](https://web.developers.google.cn/static/case-studies/zdf/image/custom-invitation-instal-10ab87790d8bb.jpg?authuser=5&hl=hr)
![下载视频以供离线观看时触发自定义安装提示。](https://web.developers.google.cn/static/case-studies/zdf/image/custom-install-prompt-bei-fcf49ed4703b6.jpg?authuser=5&hl=hr)
创建离线网页以访问下载内容
当设备未连接到互联网且用户前往离线模式下无法访问的页面时,系统会显示一个特殊页面,其中会列出之前下载的所有视频或(如果尚未下载任何内容)离线功能的简短说明。
![这个离线网页显示了所有可离线观看的内容。](https://web.developers.google.cn/static/case-studies/zdf/image/offline-page-showing-con-97273fdc6db79.png?authuser=5&hl=hr)
![离线页面显示没有可离线观看的内容。](https://web.developers.google.cn/static/case-studies/zdf/image/offline-page-showing-no-8a1022d8134c8.png?authuser=5&hl=hr)
对自适应功能使用帧速率
为了提供丰富的用户体验,ZDF PWA 包含在用户滚动或导航时发生的一些细微过渡。在低端设备上,此类动画通常会产生相反的效果,如果不能以 60 帧/秒的速率运行,应用就会让人感觉应用运行缓慢、响应速度慢。考虑到这一点,应用会在加载时通过 requestAnimationFrame()
测量实际帧速率,并在值低于特定阈值时停用所有动画。
const frameRate = new Promise(resolve => {
let lastTick;
const samples = [];
function measure() {
const tick = Date.now();
if (lastTick) samples.push(tick - lastTick);
lastTick = tick;
if (samples.length < 20) requestAnimationFrame(measure);
else {
const avg = samples.reduce((a, b) => a + b) / samples.length;
const fps = 1000 / avg;
resolve(fps);
}
}
measure();
});
即使此测量结果仅粗略了解设备性能并因每次负载而有所不同,但它仍然是做出明智决策的良好依据。值得一提的是,开发者可以实现其他自适应加载技术,具体取决于用例。这种方法的一大优势是适用于所有平台。
深色模式
深色模式是现代移动体验的热门功能。特别是在环境光线较暗的环境中观看视频,很多人更喜欢调暗的界面。ZDF PWA 不仅提供可让用户在浅色主题和深色主题之间切换的开关,还会对整个操作系统的颜色偏好设置更改做出响应。这样,在设置了根据当前时间更改主题的时间表的设备上,应用会自动更改其外观。
成果
新的渐进式 Web 应用于 2020 年 3 月以公开 Beta 版的形式默默发布,自那时以来收到了大量正面反馈。虽然 Beta 版阶段仍在进行,PWA 仍会在自己的临时网域下运行。虽然 PWA 未公开宣传,但其用户数量在稳步增长。其中许多都来自 Microsoft Store,可让 Windows 10 用户发现 PWA 并像安装平台专用应用一样安装它们。
后续操作
ZDF 计划继续为其 PWA 添加功能,包括登录进行个性化设置、跨设备和平台查看以及推送通知。