我们最近收到了许多关于渐进式 Web 应用的讨论。它们仍然是一个相对较新的模式,但其原则同样可以增强使用 vanilla JS、React、Polymer、Angular 或任何其他框架构建的应用。在本文中,我将总结一些选项和参考应用,以便您立即开始构建自己的渐进式 Web 应用。
什么是渐进式 Web 应用?
请务必注意,渐进式 Web 应用可在任何地方运行,但在现代浏览器中可发挥更强大的作用。渐进式增强是该模型的支柱。
Aaron Gustafson 将渐进式增强比作花生 M&M。花生是您的内容,巧克力外壳是您的呈现层,JavaScript 是硬糖壳。此图层的颜色可能会有所不同,具体体验也可能会因使用该图层的浏览器的功能而异。
将糖果壳视为许多渐进式 Web 应用功能的所在位置。它们是将网络之长与应用之长相结合的体验。用户在浏览器标签中第一次访问时就能体会到它们的好处,因为不需要进行任何安装。
随着用户通过反复使用与这些应用建立关系,这些应用会让糖果壳变得更加甜美:在网络连接缓慢的情况下快速加载(得益于服务工件),发送相关推送通知,并在用户的主屏幕上显示一流的图标,以便以全屏应用体验加载。他们还可以利用智能的 Web 应用安装横幅。
渐进式 Web 应用具有以下特点:
- 渐进式 - 适用于选用任何浏览器的所有用户,因为它们是以渐进式增强作为核心宗旨来开发的。
- 响应式 - 适合任何机型:桌面设备、移动设备、平板电脑或任何未来设备。
- 连接无关性 - 能够借助于服务工作线程在离线或低质量网络状况下工作。
- 类似应用 - 使用 App Shell 模型提供应用样式的导航和互动。
- 持续更新 - 在服务工作线程更新进程的作用下时刻保持最新状态。
- 安全 - 通过 TLS 提供,以防止窥探和确保内容不被篡改。
- 可发现 - W3C 清单和服务工作线程注册范围能够让搜索引擎找到它们,从而将其识别为“应用”。
- 可再互动 - 通过推送通知等功能轻松实现再互动。
- 可安装 - 用户可免去使用应用商店的麻烦,直接将对其最有用的应用“保留”在主屏幕上。
- 可链接 - 可通过网址轻松分享,无需复杂的安装。
渐进式 Web 应用也不是 Chrome for Android 独有的。下方显示了 Pokedex Progressive Web App 在 Firefox for Android(Beta 版)中正常运行,并且“添加到主屏幕”和服务工作器缓存功能正常运行。
这种“渐进式”模型的一个好处是,随着浏览器供应商提供更好的支持,您可以逐步解锁功能。当然,Pokedex 等渐进式 Web 应用在 Android 版 Opera 中也能很好地运行,但在实现方面存在一些显著差异:
如需深入了解渐进式 Web 应用,请阅读 Alex Russell 介绍该应用的原始博文。此外,Paul Kinlan 还为渐进式 Web 应用创建了非常实用的 Stack Overflow 代码,值得一试。
原则
网络应用清单
借助清单,您的网络应用可以在用户的主屏幕上呈现更接近原生应用的界面。它允许应用以全屏模式启动(不显示网址栏),提供对屏幕方向的控制,并且在 Android 版 Chrome 的最新版本中,支持为地址栏定义启动画面和主题颜色。它还用于按大小和密度定义一组图标,用于上述启动画面和主屏幕图标。
您可以在 Web Starter Kit 和 Google Chrome 示例中找到示例清单文件。Bruce Lawson 编写了一个清单生成器,Mounir Lamouri 还编写了一个实用的网络清单验证器,值得您了解。
在我的个人项目中,我依靠 realfavicongenerator 来为 Web 应用清单生成大小适当的图标,以便在 iOS、桌面设备等环境中使用。favicons Node 模块也可以在构建过程中生成类似的输出。
基于 Chromium 的浏览器(Chrome、Opera 等)目前支持 Web 应用清单,Firefox 正在积极开发支持,Edge 将其列为正在考虑。WebKit/Safari 尚未发布有关其实现此功能的意图的公开信号。
如需了解更多详情,请参阅网站开发基础中的在 Android 版 Chrome 中使用 Web 应用清单创建可安装 Web 应用。
“添加到主屏幕”横幅
Android 版 Chrome 已经支持将您的网站添加到主屏幕一段时间了,但近期版本还支持使用原生网络应用安装横幅主动建议添加网站。
为了显示应用安装提示,您的应用必须:
- 具有有效的 Web 应用清单
- 通过 HTTPS 提供(如需免费证书,请参阅 letsencrypt)
- 已注册有效的服务工作线程
- 被访问两次,这两次访问至少间隔 5 分钟
我们提供了许多应用安装横幅广告示例,涵盖基本横幅广告到更复杂的用例(例如显示相关应用)等各种类型。
用于离线缓存的 Service Worker
Service Worker 是浏览器在后台独立于网页运行的脚本。它会响应事件,包括通过其提供服务的网页发出的网络请求。Service Worker 有意设置了短的生命周期。
它会在收到事件时唤醒,并且仅在需要处理事件时运行。借助服务工作线程,您可以使用 Cache API 缓存资源,并可用于为用户提供离线体验。
服务工作线程非常适合实现离线缓存,但同时还可以针对网站或 Web 应用的重复访问实现即时加载这一重要性能。您可以缓存自己的 App Shell,以便它可以离线使用并使用 JavaScript 填充其内容。
Google Chrome 示例中提供了一组全面的 Service Worker 示例。Jake Archibald 的离线食谱是必读之作。如果您刚开始接触服务工作器,强烈建议您试用 Paul Kinlan 的您的第一个离线 Web 应用演示。
我们的团队还维护着许多 Service Worker 辅助实用程序和构建工具,这些工具有助于减少设置 Service Worker 的开销。这些库列在服务工作线程库中。其中两个主要原因是:
- sw-precache:一种构建时工具,可生成用于预缓存 Web App Shell 的 Service Worker 脚本
- sw-toolbox:一个库,用于为不经常使用的资源提供运行时缓存
Jeff Posnick 撰写了一篇名为 Offline-first, fast, with the sw-precache module 的 sw-precache 快速入门文章,并提供了一个关于该工具的 codelab,您可能会发现它们很有用。
Chrome、Opera 和 Firefox 均实现了对 Service Worker 的支持,Edge 公开表明人们对该功能感兴趣。Safari 曾通过一位工程师提议的五年计划简要提及了对其感兴趣。
用于再互动的推送通知
实际上,您可以构建 Web 应用,让用户可以在标签页之外与之互动。您可以关闭浏览器,用户甚至不需要主动使用您的 Web 应用即可享受您的体验。该功能需要同时使用 Service Worker 和 Web 应用清单,并基于前面总结的一些功能。
Push API 已在 Chrome 中实现,在 Firefox 中处于开发阶段,在 Edge 中正在考虑。Safari 尚未公开表示他们打算实现此功能。
开放网络上的推送通知是 Matt Gaunt 撰写的一篇全面介绍如何设置推送通知的文章,此外,Web 基础知识中还提供了“推送通知”Codelab。
如果您更喜欢观看视频,Chrome 团队的 Michael van Ouwerkerk 还提供了一个 6 分钟的简介来介绍推送功能。
叠加高级功能
请注意,用户体验的甜度可能会因查看 Web 应用所用的浏览器而异。您可以控制硬糖外壳。
您还可以通过这种方式将 Web 平台即将推出的其他功能(例如后台同步,用于在 Web 应用关闭时与服务器同步数据)和 Web Bluetooth(用于通过 Web 应用与蓝牙设备通信)叠加到您的渐进式 Web 应用中。
Chrome 已启用一次性后台同步功能,Jake Archibald 在视频中演示了其离线维基百科应用,并在文章中介绍了该功能的运作方式。François Beaufort 还提供了一些 Web Bluetooth 示例,如果您有兴趣试用该 API,可以参考这些示例。
支持框架
您完全可以将上述任何原则应用到您正在构建的现有应用或框架中。在构建渐进式 Web 应用时,还应注意一些其他原则,例如以用户为中心的 RAIL 性能模型和基于 FLIP 的动画。
我希望在 2016 年看到越来越多的样板和种子项目自然而然地支持将渐进式 Web 应用作为核心功能。在此之前,将这些功能添加到您自己的应用的门槛并不高,而且在我看来,非常值得。
架构
在渐进式 Web 应用模型中,您可以采用不同程度的“全押”策略,但常见的方法是围绕应用壳构建应用。这不是硬性要求,但确实有诸多好处。
App Shell 架构建议您缓存 App Shell(界面),以便它可以离线使用并使用 JavaScript 填充其内容。如果重复访问,这样还可让您在没有网络的情况下(即使您的内容最终源自网络)在屏幕上非常快速地获得有意义的像素。这可以显著提升性能。
Jeremy Keith 最近发表了评论,认为在这种类型的模型中,服务器端渲染可能不应被视为后备,而应将客户端渲染视为增强功能。这是合理的反馈。
在应用 shell 模型中,应尽可能使用服务器端渲染,并将客户端渐进式渲染用作增强功能,就像在支持服务工件时“增强”体验一样。最终可以通过多种方式来实现这一点。
建议您阅读我们关于该架构的文章,并评估如何将类似的原则最有效地应用于您自己的应用和堆栈。
入门模板
应用 Shell
app-shell
代码库包含 Application Shell 架构的近乎完整的实现。它有一个使用 Express.js 编写的后端,和一个使用 ES2015 编写的前端。
鉴于它涵盖了模型的客户端和服务器端部分,并且其中涉及到很多内容,因此需要一些时间来熟悉代码库。它就是我们目前最全面的渐进式 Web 应用起点。文档将是此项目的下一个重点。
Polymer Starter Kit
Polymer Web 应用的官方起点支持以下渐进式 Web 应用功能:
- Web 应用清单
- Android 版 Chrome 启动画面
- 使用 Platinum SW 元素的 Service Worker 离线缓存
- 使用白金推送元素的推送通知(需要手动设置)
在某些 Progressive Polymer Web 应用中,当前版本的 PSK 不支持一些更高级的性能模式(例如,应用 Shell 模型、异步加载)。
我们的目标是在 2016 年尝试将这些模式烘焙到 PSK 中,但您可以在 Rob Dodson 的 Polymer Zuperkulblog 应用和 Eric Bidelman 的精彩 Polymer Perf Patterns 演讲中找到相关的早期实验。
Web Starter Kit
我们为新的基本项目提供的起点包含以下渐进式 Web 应用功能:
- Web 应用清单
- Chrome(Android 版)启动画面
- 借助 sw-precache 实现服务工作线程预缓存
如果您更喜欢使用 vanilla JS/ES2015 且无法使用 Polymer,Web Starter Kit 作为参考点,可证明您可以重复使用或窃取代码段。
使用和不使用框架的渐进式 Web 应用
无论是否使用 JS 库和框架,社区成员已经构建了大量开源 Progressive Web App。如果您需要灵感,以下代码库可能非常有用。它们也是非常出色的应用。
Vanilla JavaScript
- Paul Lewis 的 Voice Memos 使用与
app-shell
类似的架构构建而成(编写) - Jake Archibald 的 Offline Wikipedia(离线维基百科)(视频)
- 由 Paul Kinlan 创作的 Air Horner
- Paul Lewis 的吉他调音器(编写过程)
Polymer
- Rob Dodson 的 Zuperkulblog(幻灯片)
回应
虚拟 DOM
Angular.js
- Kenneth Auchenberg 的 Timey.in - 也使用
sw-precache
进行资源预缓存
结语
如前所述,渐进式 Web 应用仍处于起步阶段,但这是一个令人兴奋的时刻,您可以尝试使用其背后的方法,看看它们能否很好地应用于您自己的 Web 应用。
Paul Kinlan 目前正在规划有关渐进式 Web 应用的 Web 基础知识指南。如果您有关于希望涵盖哪些方面的意见,欢迎随时在会话中发表评论。