使用 Workbox 将 PWA 集成到内置共享界面中

如何让您的 PWA 在系统级共享界面中显示在平台专用应用旁边

借助 Web Share Target API,您可以在用户安装渐进式 Web 应用后,在用户的系统级 Sharesheet 中显示该应用。如果您有可接收请求的服务器,这种方法非常有效,但如果没有,则很难实现。

在本文中,我们将使用 Workbox(一组用于向 Web 应用添加离线支持的 JavaScript 库)创建一个完全位于服务工作器内的共享目标网址。这样,静态网站和单页应用就可以作为共享目标,而无需专用服务器端点。

一台 Android 手机,其中“分享方式”抽屉式菜单处于打开状态。
系统级分享目标选择器,其中包含名为 Share Target Test 的安装 PWA 作为选项。

在同一页面上

如果您不熟悉 Web Share Target 的运作方式,请参阅通过 Web Share Target API 接收共享数据,详细了解相关信息。 下面是简要回顾。

实现网站分享目标功能分为两个部分。首先,更新您的网络应用清单,指明您希望应用在安装后成为共享目标。以下示例通过 POST 请求将分享内容定向到 /share 网址。它会编码为多部分表单,其中标题称为 name、文本称为 description,JPEG 图片称为 photos


"share_target": {
  "action": "/share",
  "method": "POST",
  "enctype": "multipart/form-data",
  "params": {
    "title": "name",
    "text": "description",
    "files": [
      {
        "name": "photos",
        "accept": ["image/jpeg", ".jpg"]
      }
    ]
  }
}

Service Worker 与 Workbox 共享目标

虽然通常由服务器端点处理,但您可以为分享目标使用一个巧妙的技巧,即直接在服务工件中注册路由以处理请求。这样,您的应用便可成为不含后端的分享目标。

您可以在 Workbox 中通过注册由 Service Worker 处理的路由来实现此目的。首先,从 'workbox-routing' 导入 registerRoute。请注意,它已注册 /share 路由,与 Web 应用清单示例中列出的路由相同。作为响应,它会调用 shareTargetHandler()

import { registerRoute } from 'workbox-routing';

registerRoute(
  '/share',
  shareTargetHandler,
  'POST'
);

shareTargetHandler() 函数是异步的,它会接受事件、等待表单数据,然后从中检索媒体文件。

async function shareTargetHandler ({event}) {
  const formData = await event.request.formData();
  const mediaFiles = formData.getAll('media');

  for (const mediaFile of mediaFiles) {
    // Do something with mediaFile
    // Maybe cache it or post it back to a server
  });

  // Do something with the rest of formData as you need
  // Maybe save it to IndexedDB
};

然后,您可以对这些文件执行任何操作。您可以将其缓存起来。您可以使用提取请求将其发送到某个位置。您甚至可以使用其他清单选项,例如为其他共享项提供包含一些查询参数的页面,或者将数据和指向媒体的指针存储在 Cache Storage APIIndexedDB 中。

您可以在示例应用 Fugu Journal 中试用它,并在其源代码中查看其服务工件实现。

您可以采取的一个常见做法是,在网络连接改善之前保留共享资源。Workbox 还支持定期后台同步

总结

Share Target API 是一种简单的方式,可将您的渐进式 Web 应用深度集成到用户的设备中,使其在应用间共享内容这一关键任务方面与平台专用应用不相上下。但这样做通常需要有可接收请求的服务器。通过利用 Workbox 直接在服务工件中创建共享目标路由,您的应用便可摆脱此限制,让共享目标在应用离线且没有后端时也能正常运行。

照片由 Elaine Casap 拍摄,选自 Unsplash