让您的渐进式 Web 应用不像网站,而是如同“真正的”应用
当您玩渐进式 Web 应用时尚宾果时,可以放心地将“PWA 只是网站”设置为“网站”。Microsoft 的 PWA 文档认可,我们在这一网站上说过,甚至 PWA 提名者 Frances Berriman 和 Alex Russell 也写了这样的内容。是的,PWA 只是网站,但其作用远不止于此。如果操作得当,PWA 不会像一个网站,而是如一个“真实”应用。那么,像个真实应用是什么意思呢?
为了解答这个问题,我以 Apple 播客应用为例。它支持桌面设备上的 macOS 以及移动设备的 iOS(分别为 iPadOS)和 iPadOS。 虽然播客是一款媒体应用,但我借助它来说明的核心理念同样适用于其他类别的应用。
![一部 iPhone 和一台 MacBook 并排显示,两部手机都在运行 Google 播客应用。](https://web.developers.google.cn/static/articles/app-like-pwas/image/an-iphone-a-macbook-side.png?authuser=9&hl=uk)
可离线运行
如果您后退一步,回想一下您的手机或桌面设备上的平台专用应用程序,您会发现有一个明显突出的点:您永远不会得到任何东西。即使我处于离线状态,在播客应用中也总能找到一些内容。没有网络连接时,应用仍会正常打开。热门搜索排行榜部分不会显示任何内容,而是回退到显示与重试按钮配对的目前无法连接消息。这可能不是最受欢迎的体验,但我有收获。
![没有网络连接时,播客应用显示“目前无法连接。”信息消息。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-app-showing-1a38f7777604b.png?authuser=9&hl=uk)
播客应用遵循所谓的应用 Shell 模型。显示核心应用所需的所有静态内容都将缓存在本地,包括左侧菜单图标和核心播放器界面图标等装饰图片。热门排行榜数据等动态内容仅按需加载,加载失败时会提供本地缓存的后备内容。 阅读 App Shell 模型一文,了解如何将此架构模型应用于您的 Web 应用。
可离线播放内容和媒体
在离线状态下,我仍然可以通过左侧抽屉式导航栏前往 Downloaded 部分,欣赏已下载的播客分集,这些播客分集可以播放,并与所有元数据(例如海报图片和说明)一起显示。
![播客应用,其中包含播放的播客分集。](https://web.developers.google.cn/static/articles/app-like-pwas/image/podcasts-app-a-downloade-2a1132796df05.png?authuser=9&hl=uk)
可以从缓存中传送之前下载的媒体内容,例如,使用 Workbox 库中的传送缓存的音频和视频配方。 其他内容始终可以存储在缓存或 IndexedDB 中。如需了解所有详情以及何时应使用哪种存储技术,请阅读 Web 存储一文。如果您的某些数据应永久存储,而又不会有在可用内存量不足时被完全清除的风险,您可以使用 Persistent Storage API。
主动式后台下载
恢复联网后,我当然可以搜索包含“http 203
”这样查询的内容;当我决定订阅搜索结果时,系统会立即下载该系列的最新一集,无需提问,HTTP 203 播客。
![在订阅播客后立即下载最新一集的播客应用。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-app-download-9921ed2cb417a.png?authuser=9&hl=uk)
下载播客分集是一项可能需要更长时间的操作。借助 Background Fetch API,您可以将下载委托给浏览器,由浏览器在后台处理下载。 在 Android 上,浏览器甚至可以将这些下载内容进一步委托给操作系统,这样浏览器就无需持续运行了。 下载完成后,应用的 Service Worker 将会唤醒,您可以决定如何处理响应。
与其他应用共享内容并与之互动
播客应用可与其他应用自然集成。例如,当我右键点击喜欢的分集时,就可以将其分享到设备上的其他应用(例如“信息”应用)。该应用还会自然而然地与系统剪贴板集成。我可以右键点击任一分集,然后复制指向该分集的链接。
![在选择了“分享分集 → 消息”选项的情况下,针对某个播客分集调用了 Google 播客应用的上下文菜单。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-apps-contex-baa82d1b8e86.png?authuser=9&hl=uk)
借助 Web Share API 和 Web Share Target API,您的应用可与设备上的其他应用分享和接收文本、文件和链接。尽管 Web 应用还无法将菜单项添加到操作系统的内置右键菜单,但还有许多其他方法可与设备上的其他应用建立链接,或链接自设备上的其他应用。 借助 Async Clipboard API,您可以通过编程方式在系统剪贴板中读取和写入文本和图片数据(PNG 图片)。 在 Android 设备上,您可以使用 Contact Picker API 从设备的联系人管理器中选择条目。如果您同时提供平台专用应用和 PWA,您可以使用 Get installed Related Apps API 检查是否已安装平台专用应用。在这种情况下,您无需鼓励用户安装 PWA 或接受网络推送通知。
后台应用刷新
在“播客”应用的设置中,我可以将应用配置为自动下载新分集。这样,我甚至不用考虑这件事,更新后的内容会始终显示在那里。魔法。
![播客应用的设置菜单中的“常规”部分,其中的“刷新播客”选项设为“每小时”。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-apps-settin-ddcbe94c88499.png?authuser=9&hl=uk)
借助 Periodic Background Sync API,您的应用可以在后台定期刷新其内容,而无需运行。 这意味着我们会主动提供新内容,因此您的用户无论何时决定,都可以立即开始深入研究。
状态已通过云同步
与此同时,我的订阅会在我拥有的所有设备上同步。在无缝衔接的世界中,我无需担心手动使播客订阅保持同步。同样,我也不用担心自己移动设备的存储空间会被我在桌面设备上听过的分集所占用。播放状态会保持同步,并自动删除已收听的分集。
![播客应用的“设置”菜单中的“高级”部分,其中的“在设备间同步订阅”选项处于启用状态。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-apps-settin-9ea8647cdaefb.png?authuser=9&hl=uk)
同步应用状态数据是一项可委托给 Background Sync API 的任务。同步操作本身并不一定立即发生,只是最终,甚至可能在用户已经再次关闭应用时执行。
硬件媒体键控件
当我忙于处理其他应用(例如在 Chrome 浏览器中阅读新闻页面)时,仍可以使用笔记本电脑上的媒体键控制 Google 播客应用。 您无需为了快进或快退而切换到应用程序。
![Apple MacBook Pro 魔术键盘,带有带注释的媒体键。](https://web.developers.google.cn/static/articles/app-like-pwas/image/apple-macbook-pro-magic-k-aff6291456fc4.png?authuser=9&hl=uk)
Media Session API 支持媒体键。这样,用户就可以使用实体键盘、耳机上的硬件媒体键,甚至可以通过智能手表上的软件媒体键控制 Web 应用。 使跳转操作顺畅的另一种方法是,当用户跳转到内容的大部分内容时(例如,跳过片头字幕或章节边界)时发送振动模式。
多任务处理和应用快捷方式
当然,我可以随时从任意位置使用多任务处理功能返回 Google 播客应用。该应用有一个清晰可辨的图标,我也可以将其放在桌面或应用基座上,这样当我需要播客时可以立即启动。
![macOS 任务切换器,带有多个应用图标供您选择,其中一个就是 Google 播客应用。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-macos-task-switcher-908786af218a7.png?authuser=9&hl=uk)
桌面设备和移动设备上的渐进式 Web 应用均可安装到主屏幕、“开始”菜单或快捷应用栏。安装可以根据主动提示进行,也可以完全由应用开发者控制。 如何才能安装?一文介绍了您需要了解的所有内容。 当多任务处理时,PWA 看起来独立于浏览器。
上下文菜单中的快速操作
用户可在 Dock 中通过相应应用的上下文菜单执行最常见的应用操作,包括搜索新内容和查看新分集。通过选项菜单,我还可以决定在登录时打开该应用。
![播客应用图标上下文菜单,显示了“搜索”和“查看新分集”选项。](https://web.developers.google.cn/static/articles/app-like-pwas/image/podcasts-app-icon-context-031ae939ff38d.png?authuser=9&hl=uk)
作为默认应用
其他 iOS 应用(甚至是网站或电子邮件)可以利用 podcasts://
网址架构与 Google 播客应用集成。如果我在浏览器中点击 podcasts://podcasts.apple.com/podcast/the-css-podcast/id1042283903
之类的链接,就会直接进入“播客”应用,并可以决定是订阅还是收听该播客。
![Chrome 浏览器显示一个确认对话框,询问用户是否要打开 Google 播客应用。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-chrome-browser-showin-8f6d4d51b3265.png?authuser=9&hl=uk)
目前还不能处理完全自定义网址方案,但有正在制定针对 PWA 的网址协议处理方案。目前,带有 web+
架构前缀的 registerProtocolHandler()
是最佳替代方案。
本地文件系统集成
您可能不会立即想到,但 Google 播客应用已经与本地文件系统自然集成。我在笔记本电脑上下载播客分集后,它会存储在~/Library/Group Containers/243LU875E5.groups.com.apple.podcasts/Library/Cache
中。与 ~/Documents
不同的是,此目录显然不能供普通用户直接访问,但它确实存在。离线内容部分提及了除文件以外的其他存储机制。
![macOS Finder 已导航到播客应用的系统目录。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-macos-finder-navigate-3fcbbc6e0f6c2.png?authuser=9&hl=uk)
File System Access API 可让开发者访问设备的本地文件系统。您可以直接使用该 API,也可以通过 browser-fs-access 支持库使用该库,该支持库以透明的方式为不支持该 API 的浏览器提供了回退机制。 出于安全考虑,系统目录无法通过网络访问。
平台外观和风格
对于播客这样的 iOS 应用来说,有一点不言自明:所有文本标签都不可选择,并且所有文本都与机器的系统字体融合在一起。此外,我选择的系统颜色主题(深色模式)也遵循我的设置。
![采用深色模式的 Google 播客应用。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-app-dark-mo-e950b02a59358.png?authuser=9&hl=uk)
![浅色模式下的 Google 播客应用。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-app-light-m-8e2eef2a9208e.png?authuser=9&hl=uk)
通过利用值为 none
的 user-select
CSS 属性,您可以防止界面元素被意外选择。
但请注意,不要滥用此属性使应用内容不可选择。
它应该仅用于按钮文本等界面元素。font-family
CSS 属性的 system-ui 值可让您指定应用要使用的默认界面字体。最后,您的应用可以遵循用户的配色方案偏好设置,即遵循用户的 prefers-color-scheme
选择,并提供可选的深色模式切换开关来覆盖该颜色。
另一个需要决定的对象可能是,当达到滚动区域边界时,浏览器应执行什么操作,例如实现自定义“拉取刷新”。这可通过 overscroll-behavior
CSS 属性实现。
自定义标题栏
当您查看 Google 播客应用窗口时,您会发现它并没有像 Safari 浏览器窗口等经典集成的标题栏和工具栏,而是提供一种自定义体验,就像固定在播放器主窗口上的边栏一样。
![Safari 浏览器集成的图块栏和工具栏。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-safari-browsers-inte-f6013fe50cc67.png?authuser=9&hl=uk)
![播客应用的自定义拆分自定义标题栏。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-apps-custom-3bbf207aaf9b4.png?authuser=9&hl=uk)
我们目前正在开发标题栏自定义功能,不过目前还无法实现。不过,您可以(并且应该)指定 Web 应用清单的 display
和 theme-color
属性,以确定应用窗口的外观和风格,并决定应显示哪些默认浏览器控件(可能不显示任何控件)。
明快的动画
在播客中,应用内动画简洁明了、流畅。例如,当我打开右侧的剧集备注抽屉式导航栏时,它优雅地滑入。当我从下载内容中移除一个剧集后,其余剧集将向上浮动,并占用被删除剧集所释放的屏幕空间。
![“分集备注”抽屉式导航栏处于展开状态的 Google 播客应用。](https://web.developers.google.cn/static/articles/app-like-pwas/image/the-podcasts-app-the-ep-a8396a577f27b.png?authuser=9&hl=uk)
如果您考虑动画与性能一文中所述的一些最佳实践,则一定可以在网络上实现高性能动画。 通过使用 CSS 滚动贴靠功能,可以大幅改进分页内容或媒体轮播界面中常见的滚动动画。如需完全控制,您可以使用 Web Animations API。
内容在应用外显示
iOS 上的“播客”应用可以在实际应用以外的位置显示内容,例如在系统的“微件”视图中,或以 Siri 建议的形式。采用基于使用情况的主动号召性用语(只需点按一下即可进行互动),可以大幅提高 Google 播客等应用的再互动率。
![iOS widget 视图,其中显示了“播客”应用建议新的播客分集。](https://web.developers.google.cn/static/articles/app-like-pwas/image/ios-widget-view-showing-90d45b3921783.png?authuser=9&hl=uk)
您的应用可通过 Content Index API 告知浏览器 PWA 的哪些内容可离线使用。 这样一来,浏览器便可以在主应用之外显示此类内容。通过在应用中将有趣的内容标记为适合可语音音频播放,并通常使用结构化标记,您可以帮助搜索引擎和 Google 助理等虚拟助理在理想情况下展示您提供的产品/服务。
锁定屏幕媒体控件微件
当播客分集播放时,播客应用会在锁定屏幕上显示一个精美的控制 widget,其中包含分集海报图片、分集标题和播客名称等元数据。
![锁定屏幕上的 iOS 媒体播放微件,显示了包含丰富元数据的播客分集。](https://web.developers.google.cn/static/articles/app-like-pwas/image/ios-media-playback-widget-646d9ece0ed78.png?authuser=9&hl=uk)
借助 Media Session API,您可以指定海报图片、曲目标题等元数据,然后它们会显示在锁定屏幕、智能手表或浏览器中的其他媒体微件上。
推送通知
推送通知已经在 Web 上变得有点令人厌烦(尽管通知提示现在更加安静了)。但如果使用得当,它们可以带来很多价值。 例如,iOS 播客应用可以选择在我订阅的播客有新分集时通知我或推荐新分集,还可以提醒我有关新的应用功能。
![iOS 播客应用中的“通知”设置界面,其中显示“新分集”通知切换开关已激活。](https://web.developers.google.cn/static/articles/app-like-pwas/image/ios-podcasts-app-the-no-9c503d696ee53.png?authuser=9&hl=uk)
借助 Push API,您的应用可以接收推送通知,以便您向用户通知 PWA 周围的值得注意的事件。 对于应在未来某个已知时间触发且不需要网络连接的通知,您可以使用 Notification Triggers API。
应用图标标记
每当我订阅的某个播客有新分集时,“播客”主屏幕图标上会显示一个应用图标标记,再次鼓励我以不会侵扰性的方式再次与该应用互动。
![iOS 设置界面,显示“徽章”切换开关已激活。](https://web.developers.google.cn/static/articles/app-like-pwas/image/ios-settings-screen-showi-8b563100af8df.png?authuser=9&hl=uk)
您可以使用 Badging API 设置应用图标标记。如果您的 PWA 具有“未读”项目的概念,或者您需要一种不突兀的方式将用户的注意力重新吸引到应用,这种方法特别有用。
媒体播放优先于节能设置
当播客媒体播放时,屏幕可能会关闭,但系统不会进入待机模式。 应用也可以选择使屏幕保持唤醒状态,例如显示歌词或字幕。
![“Energy Saver”部分中的 macOS 偏好设置。](https://web.developers.google.cn/static/articles/app-like-pwas/image/macos-preferences-the-e-89b8e24f8e63.png?authuser=9&hl=uk)
Screen Wake Lock API 可让您防止屏幕关闭。在网页上播放媒体会自动阻止系统进入待机模式。
通过应用商店发现应用
虽然播客应用是 macOS 桌面设备体验的一部分,但在 iOS 设备上,您需要从 App Store 安装它。
快速搜索 podcast
、podcasts
或 apple podcasts
会立即打开 App Store 中的应用。
![在 iOS App Store 中搜索“播客”会显示“播客”应用。](https://web.developers.google.cn/static/articles/app-like-pwas/image/ios-app-store-search-po-130f76d3ee97d.png?authuser=9&hl=uk)
虽然 Apple 不允许在 App Store 中使用 PWA,但在 Android 设备上,您可以提交封装在 Trusted Web Activity 中的 PWA。
bubblewrap
脚本使此操作成为一项轻松的操作。此脚本也是 PWABuilder 的 Android 应用导出功能在内部提供支持,您无需接触命令行即可使用该功能。
特性摘要
下表简要概述了所有功能,并提供了可用于在网络上实现这些功能的实用资源列表。
总结
PWA 自 2015 年推出以来取得了长足的进步。在 Project Fugu 🐡? 的背景下,跨公司的 Chromium 团队正努力弥补最后的不足。 即使只遵循本文中的部分建议,您也可以逐条更接近那种类似应用的感觉,并让用户忘记他们处理的只是“网站”,因为说实话,大多数人并不在意应用的构建方式(以及为什么应该这样做),只要它让人感觉像一个真正的应用就行。
致谢
本文由 Kayce Basques、Joe Medley、Joshua Bell、Dion Almaer、Ade Oshineye、Pete LePage、Sam Thorogood、Reilly Yaskin、Reilly Grant 和