最近有许多关于渐进式 Web 应用的热议话题。它们仍然是一个相对较新的模式,但其原则同样可以增强使用 vanilla JS、React、Polymer、Angular 或任何其他框架构建的应用。在这篇博文中,我将总结一些选项和参考应用,帮助您立即开始使用您自己的渐进式 Web 应用。
什么是渐进式 Web 应用?
请务必注意,渐进式 Web 应用可随时随地运行,但在现代浏览器中会更加强大。渐进式增强是该模型的支柱。
Aaron Gustafson 将渐进式增强比作花生 M&M。花生就是您的内容,巧克力涂层是演示层,而 JavaScript 就是硬糖壳。这一层的颜色不尽相同,而具体体验可能会因使用该层的浏览器功能而异。
您可以把糖果外壳看成是很多渐进式 Web 应用功能的地方。它们是将网络之长与应用之长相结合的体验。用户在浏览器标签页中第一次访问时就很有用,无需安装。
当用户通过重复使用与这些应用建立关系时,它们会让糖果外壳更甜蜜:在慢速网络连接下可以非常快速地加载(得益于 Service Worker),发送相关的推送通知,并在用户的主屏幕上放置一个一流的图标,以全屏应用体验的形式加载它们。他们还可以利用智能的 Web 应用安装横幅。
![用于提升互动度的网络应用安装横幅,从用户的主屏幕启动,在 Chrome(Android 版)中的启动画面,可与 Service Worker 离线工作](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/web-app-install-banners-f9228e2c96da6.jpg?authuser=9&hl=cs)
渐进式 Web 应用
- 渐进式 - 适用于每位用户(无论选择使用哪种浏览器),因为这些应用是以渐进式增强作为核心租户构建的。
- 自适应 - 适应任何外形规格,包括桌面设备、移动设备、平板电脑或任何未来设备。
- 连接无关性 - 能够借助 Service Worker 离线工作或在质量不佳的网络状态下工作。
- 类似应用 - 使用 App Shell 模型提供应用样式的导航和互动。
- 持续更新 - 在 Service Worker 的更新流程的帮助下始终保持最新状态。
- 安全 - 通过 TLS 传送,以防止窥探,并确保内容未被篡改。
- 可发现 - W3C 清单和 Service Worker 注册范围允许搜索引擎找到它们,因此可被识别为“应用”。
- 可再互动 - 通过推送通知等功能轻松实现再互动。
- 可安装 - 让用户无需前往应用商店,就能将他们认为最有用的应用“保留”在主屏幕上。
- 可链接 - 可通过网址轻松分享,无需复杂的安装。
渐进式 Web 应用也不是 Chrome(Android 版)所独有。下面我们可以看到 Pokedex 渐进式 Web 应用在 Firefox for Android(Beta 版)中正常运行,具有早期的“添加到主屏幕”功能和 Service Worker 缓存功能正常运行。
![在 Android 版 Firefox 中正常运行的渐进式 Web 应用](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/progressive-web-apps-work-27c4b87c1d385.jpg?authuser=9&hl=cs)
此模式的“渐进式”性质的一个优点是,随着浏览器供应商为这些功能提供更好的支持,这些功能可以逐步解锁。当然,Pokedex 等渐进式 Web 应用同样适用于 Android 上的 Opera,但在实现方面也存在一些显著差异:
![可在 Android 版 Opera 中运行的渐进式 Web 应用](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/progressive-web-apps-work-4d3f294bdd8bd.jpg?authuser=9&hl=cs)
如需深入了解渐进式 Web 应用,请参阅 Alex Russell 关于介绍这些应用的原创博文。此外,Paul Kinlan 还为渐进式 Web 应用创建了非常实用的 Stack Overflow 代码,值得一试。
原则
Web 应用清单
该清单可让您的 Web 应用在用户的主屏幕上呈现更接近原生状态的内容。它允许应用以全屏模式启动(不显示网址栏),并且可以控制屏幕方向。在 Android 版 Chrome 的近期版本中,它支持为地址栏定义启动画面和主题颜色。它还可用于按尺寸和密度定义一组图标,这些图标用于前面提到的启动画面和主屏幕图标。
![添加到主屏幕、从主屏幕启动,以及类似应用的全屏体验。](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/add-home-screen-launch-8bc82e53bec3f.jpg?authuser=9&hl=cs)
您可以在 Web Starter Kit 和 Google Chrome 示例中找到示例清单文件。Bruce Lawson 编写了清单生成器,Mounir Lamouri 也编写了一款方便使用的网页清单验证器,值得一试。
在我的个人项目中,我依靠 realfavicongenerator 来为 Web 应用清单生成大小适当的图标,以便在 iOS、桌面设备等环境中使用。在构建流程中,网站图标节点模块也可以实现类似的输出。
基于 Chromium 的浏览器(Chrome、Opera 等)目前支持 Web 应用清单,Firefox 会积极开发支持,而 Edge 则将这些清单列为正在考虑中。WebKit/Safari 尚未发布有关其实现此功能的意图的公开信号。
有关详情,请参阅网站开发基础上的在 Chrome(Android 版)中使用 Web 应用清单安装可安装的 Web 应用。
“添加到主屏幕”横幅
Android 版 Chrome 暂时支持将网站添加到主屏幕,但最新的版本还支持使用原生网络应用安装横幅主动建议添加网站。
![在 Chrome(Android 版)中显示 Web 应用安装横幅提示的语音备忘录演示应用](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/the-voice-memos-demo-appl-9361e1a793b63.jpg?authuser=9&hl=cs)
若要让应用安装提示显示,您的应用必须满足以下条件:
- 具有有效的 Web 应用清单
- 通过 HTTPS 提供(有关免费证书,请参阅 letsencrypt)
- 注册了有效的 Service Worker
- 访问过两次,每次访问至少间隔 5 分钟
我们提供很多应用安装横幅广告示例,从基本横幅广告到展示相关应用等更复杂的用例。
用于离线缓存的 Service Worker
Service Worker 是一种独立于网页在后台运行的脚本。它会响应事件,包括从它提供的页面发出的网络请求。Service Worker 有意设置了短的生命周期。
它会在收到事件时唤醒,并且只在需要处理事件时运行。Service Worker 可让您使用 Cache API 缓存资源,并可用于为用户提供离线体验。
Service Worker 功能强大,可用于离线缓存,但也为重复访问网站或 Web 应用的即时加载提供显著的性能优势。您可以将 App Shell 缓存,以便它离线工作并使用 JavaScript 填充其内容。
![Service Worker 缓存 App Shell,使其在没有网络的情况下加载](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/service-worker-caching-t-6a32e7591aaf6.jpg?authuser=9&hl=cs)
Google Chrome 示例上提供了一系列全面的 Service Worker 示例。Jake Archibald 的离线实战宝典是一本必读,如果不熟悉 Service Worker,我强烈建议尝试一下 Paul Kinlan 的首个离线 Web 应用演示。
我们的团队还维护着许多 Service Worker 帮助程序实用程序和构建工具,我们认为这些工具有助于减少设置 Service Worker 的开销。Service Worker 库中列出了它们。其中有两个主要功能:
- sw-precache:一种构建时工具,可生成用于预缓存 Web App Shell 的 Service Worker 脚本
- sw-toolbox:为不常用的资源提供运行时缓存的库
Jeff Posnick 撰写了一篇关于 sw-precache 的快速入门,名为 Offline-first, fast, with the sw-precache module,以及同一工具的 Codelab,可能会对您有所帮助。
Chrome、Opera 和 Firefox 均实现了对 Service Worker 的支持,Edge 公开表明人们对该功能感兴趣。Safari 曾通过一位工程师提议的五年计划简要提及了对其感兴趣。
用于再互动的推送通知
您可以有效地构建用户可在标签页外与之互动的 Web 应用。浏览器可以关闭,用户甚至不需要主动使用您的 Web 应用就可以享受您的体验。该功能需要 Service Worker 和 Web 应用清单,并以前面总结的一些功能为基础进行构建。
Push API 已在 Chrome 中实现,在 Firefox 中处于开发阶段,并且已在 Edge 中考虑实现。Safari 尚未公开表明其打算实施此功能的意图。
开放网络中的推送通知全面介绍了 Matt Gaunt 如何对推送设置进行设置,Web Fundamentals 中也提供了推送通知 Codelab。
![Facebook 移动网站上的网络推送通知](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/web-push-notification-th-2fb064af3df45.jpg?authuser=9&hl=cs)
如果您更喜欢看视频,Chrome 团队的 Michael van Ouwerkerk 也提供了 6 分钟的推送介绍。
高级功能中的分层
请注意,用户体验的甜度可能有所不同,具体取决于用来查看 Web 应用的浏览器。硬糖果壳由您自己掌控。
网络平台即将推出的其他功能,如后台同步(即使在您的 Web 应用关闭时,用于与服务器同步数据)和 Web 蓝牙(用于从 Web 应用与蓝牙设备通信)等,也可以通过这种方式分层放置到您的渐进式 Web 应用中。
Chrome 中启用了“单次后台同步”,Jake Archibald 制作了一个视频,其中展示了他的离线维基百科应用和相关文章,演示了如何使用该技术。Francois Beaufort 还提供了许多网络蓝牙示例,如果您有兴趣试用该 API,可以参考。
支持框架
您完全可以将上述任何原则应用到您正在构建的现有应用或框架中。在构建 Progressive Web App 时,还有几个值得注意的原则是以用户为中心的 RAIL 性能模型和基于 FLIP 的动画。
我希望在 2016 年看到越来越多的样板和种子项目自然而然地支持将渐进式 Web 应用作为核心功能。在此之前,为您自己的应用添加这些功能的门槛并不高,并且非常值得一试。
架构
渐进式网页应用模型中的“全包式”机制在不同层面上有所不同,但常用的一种方法是围绕应用 Shell 构建这种模型。这不是硬性要求,但有几个好处。
应用 Shell 架构建议缓存您的 App Shell(界面),以便它可以离线工作并使用 JavaScript 填充其内容。在重复访问中,这可以让您在没有网络的情况下快速在屏幕上获取有意义的像素,即使您的内容最终来自该网络也是如此。这会带来显著的性能提升。
![可视化应用 Shell 分解应用界面,例如抽屉式导航栏和主要内容区域](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/the-application-shell-bei-6996763948f43.jpg?authuser=9&hl=cs)
Jeremy Keith 最近评论说,在此类模型中,不应将服务器端渲染视为后备,而应将客户端渲染视为增强功能。这是公平的反馈。
在应用 Shell 模型中,应尽可能使用服务器端渲染,而将客户端渐进式渲染用作增强功能,就像我们在支持 Service Worker 时“增强”体验一样。最终可以通过多种方式来解决问题。
建议您阅读我们关于此架构的文章,并评估类似原则如何才能最好地应用于您自己的应用和堆栈。
使用入门样板
应用 Shell
app-shell
代码库包含 Application Shell 架构的近乎完整的实现。它有一个使用 Express.js 编写的后端,和一个使用 ES2015 编写的前端。
鉴于它涵盖了模型的客户端和服务器端部分,并且其中涉及到很多内容,因此需要一些时间来熟悉代码库。它就是我们目前最全面的渐进式 Web 应用起点。Google 文档是此项目的下一个重点。
Polymer 入门套件
Polymer Web 应用的官方起点支持以下渐进式 Web 应用功能:
- Web 应用清单
- Chrome(Android 版)启动画面
- 使用 Platinum SW 元素的 Service Worker 离线缓存
- 包含白金推送元素的推送通知(需要手动设置)
![显示内置渐进式 Web 应用功能的 Polymer 入门套件](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/polymer-starter-kit-displ-3f2146d0dce31.jpg?authuser=9&hl=cs)
在某些 Progressive Polymer Web 应用中,当前版本的 PSK 不支持一些更高级的性能模式(例如应用 Shell 模型、异步加载)。
我们的目标是在 2016 年尝试将这些模式烘焙成 PSK,但您可以在 Rob Dodson 的 Polymer Zuperkulblog 应用和 Eric Bidelman 的精彩 Polymer Perf Patterns 演讲中找到相关的早期实验。
Web Starter Kit
对于新的 vanilla 项目,我们的专业起点包括以下 Progressive Web App 功能:
- Web 应用清单
- Chrome(Android 版)启动画面
- 借助 sw-precache,让 Service Worker 能够进行预缓存
如果您倾向于使用 vanilla JS/ES2015 且无法使用 Polymer,Web Starter Kit 作为参考点,可证明您可以重复使用或窃取代码段。
使用和不使用框架的渐进式 Web 应用
无论是否使用 JS 库和框架,社区成员已经构建了大量开源 Progressive Web App。如果您想找点灵感,不妨参考以下代码库。它们也是非常棒的应用。
![使用 React、Polymer、虚拟 DOM 和 AngularJS 实现的渐进式 Web 应用](https://developer.chrome.google.cn/static/blog/getting-started-pwa/image/progressive-web-apps-impl-de466194f58d1.jpg?authuser=9&hl=cs)
原生 JavaScript
- Paul Lewis 的 Voice Memos 使用与
app-shell
类似的架构构建而成(撰写内容) - 离线维基百科,作者:Jake Archibald(视频)
- 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 Fundamentals 指南,如果您对相关领域有任何意见或建议,请随时在讨论帖中发表评论。