跳到主要内容

📦 plugin-pwa

道格龙(Docusaurus)插件,基于 Workbox 实现 PWA 支持。该插件仅在生产环境构建时生成 Service Worker,让你的文档站点完全符合 PWA 标准,支持离线访问和安装。

安装

npm install --save @docusaurus/plugin-pwa

配置

./static/manifest.json 处创建 PWA manifest

docusaurus.config.js 中添加最简 PWA 配置,例如:

docusaurus.config.js
export default {
plugins: [
[
'@docusaurus/plugin-pwa',
{
debug: true,
offlineModeActivationStrategies: [
'appInstalled',
'standalone',
'queryString',
],
pwaHead: [
{
tagName: 'link',
rel: 'icon',
href: '/img/docusaurus.png',
},
{
tagName: 'link',
rel: 'manifest',
href: '/manifest.json', // 你的 PWA manifest
},
{
tagName: 'meta',
name: 'theme-color',
content: 'rgb(37, 194, 160)',
},
],
},
],
],
};

渐进式 Web 应用(PWA)

仅安装 service worker 并不足以让你的应用成为 PWA。你还需要至少包含 Web App Manifest 并在 <head> 中添加正确的标签(详见 Options > pwaHead)。

部署后,你可以使用 Lighthouse 对站点进行 PWA 检查。

更完整的 PWA 要求可参考 PWA 检查清单

应用安装支持

如果浏览器支持,你可以将道格龙站点安装为应用。

安装过程演示。浏览器地址栏出现按钮,点击后弹出&quot;安装此应用?&quot;对话框,点击&quot;安装&quot;后,操作系统中打开了一个新的应用窗口,显示道格龙首页。

备注

应用安装需要 HTTPS 协议和有效的 manifest 文件。

离线模式(预缓存)

我们通过 service worker 预缓存机制,让用户可以离线浏览道格龙站点。

workbox-precaching 页面解释了其原理:

service worker 的一个特性是在安装时将一组文件保存到缓存中。这通常被称为"预缓存",因为你在 service worker 启用前就缓存了内容。

这样做的主要原因是开发者可以控制缓存,决定文件何时、如何缓存,以及无需访问网络即可将其提供给浏览器,从而实现离线 Web 应用。

Workbox 简化了预缓存的 API,并确保高效下载资源,大大减轻了开发负担。

默认情况下,站点被安装为应用时会启用离线模式。详见 offlineModeActivationStrategies 选项。

站点被预缓存后,service worker 会为后续访问提供缓存内容。当有新构建和新 service worker 部署时,新 worker 会开始安装并进入等待状态。此时会弹出刷新提示,建议用户刷新页面以获取新内容。在用户清除应用缓存或点击弹窗的 reload 按钮前,service worker 会继续提供旧内容。

注意

离线模式/预缓存需要提前下载站点所有静态资源,可能会消耗不必要的带宽。并不建议所有站点都启用。

选项

debug

  • 类型:boolean
  • 默认值:false

开启调试模式:

  • 输出 Workbox 日志
  • 输出额外的道格龙日志
  • 输出未优化的 SW 文件
  • 输出 source map

offlineModeActivationStrategies

  • 类型:('appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always')[]
  • 默认值:['appInstalled', 'queryString', 'standalone']

用于激活离线模式的策略:

  • appInstalled:用户已将站点安装为应用时激活(并非 100% 可靠)
  • standalone:以独立应用模式运行时激活(PWA 安装后常见)
  • queryString:URL 查询参数包含 offlineMode=true 时激活(便于 PWA 调试)
  • mobile:移动端用户(宽度 <= 996px)激活
  • saveData:用户设置了 navigator.connection.saveData === true 时激活
  • always:对所有用户激活
注意

请谨慎使用:部分用户可能不喜欢被强制进入离线模式。

危险

无法可靠检测页面是否以 PWA 方式渲染。

appinstalled 事件已被 规范移除navigator.getInstalledRelatedApps() API 仅在新版 Chrome 支持,且需在 manifest 中声明 related_applications

standalone 策略 是激活离线模式的较好兜底方案(至少在已安装应用时有效)。

injectManifestConfig

Workbox 选项,传递给 workbox.injectManifest()。你可以通过它控制哪些资源会被预缓存、可离线访问。

  • 类型:InjectManifestOptions
  • 默认值:{}
docusaurus.config.js
export default {
plugins: [
[
'@docusaurus/plugin-pwa',
{
injectManifestConfig: {
manifestTransforms: [
// ...
],
modifyURLPrefix: {
// ...
},
// 我们已自动将常规静态资源(HTML、图片等)加入离线缓存
// 你可以根据需要添加更多文件
globPatterns: ['**/*.{pdf,docx,xlsx}'],
// ...
},
},
],
],
};

pwaHead

  • 类型:({ tagName: string; [attributeName: string]: string })[]
  • 默认值:[]

包含 tagName 及属性键值对的对象数组,注入到 <head> 标签。理论上可注入任意 head 标签,推荐用于让站点符合 PWA 标准。以下为常用标签示例:

export default {
plugins: [
[
'@docusaurus/plugin-pwa',
{
pwaHead: [
{
tagName: 'link',
rel: 'icon',
href: '/img/docusaurus.png',
},
{
tagName: 'link',
rel: 'manifest',
href: '/manifest.json',
},
{
tagName: 'meta',
name: 'theme-color',
content: 'rgb(37, 194, 160)',
},
{
tagName: 'meta',
name: 'apple-mobile-web-app-capable',
content: 'yes',
},
{
tagName: 'meta',
name: 'apple-mobile-web-app-status-bar-style',
content: '#000',
},
{
tagName: 'link',
rel: 'apple-touch-icon',
href: '/img/docusaurus.png',
},
{
tagName: 'link',
rel: 'mask-icon',
href: '/img/docusaurus.svg',
color: 'rgb(37, 194, 160)',
},
{
tagName: 'meta',
name: 'msapplication-TileImage',
content: '/img/docusaurus.png',
},
{
tagName: 'meta',
name: 'msapplication-TileColor',
content: '#000',
},
],
},
],
],
};

swCustom

  • 类型:string | undefined
  • 默认值:undefined

用于添加自定义 Workbox 规则。你可以在这里实现任意 service worker 逻辑,充分利用 workbox 库。代码会被转译,可直接使用 ES6+ 语法。

例如,缓存外部资源:

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

// 默认导出函数,接收一些有用参数
export default function swCustom(params) {
const {
debug, // :boolean
offlineMode, // :boolean
} = params;

// 缓存外部资源响应
registerRoute((context) => {
return [
/graph\.facebook\.com\/.*\/picture/,
/netlify\.com\/img/,
/avatars1\.githubusercontent/,
].some((regex) => context.url.href.match(regex));
}, new StaleWhileRevalidate());
}

模块需导出 default 函数,参数如上。

swRegister

  • 类型:string | false
  • 默认值:'docusaurus-plugin-pwa/src/registerSW.js'

在道格龙应用启动前注册 service worker。默认的 registerSW.js 已满足简单注册需求。

传递 false 可完全禁用注册。

Manifest 示例

道格龙站点 manifest 可供参考:

{
"name": "Docusaurus",
"short_name": "Docusaurus",
"theme_color": "#2196f3",
"background_color": "#424242",
"display": "standalone",
"scope": "./",
"start_url": "./index.html",
"related_applications": [
{
"platform": "webapp",
"url": "https://docusaurus.io/manifest.json"
}
],
"icons": [
{
"src": "img/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "img/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "img/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "img/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "img/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "img/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "img/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "img/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

自定义刷新弹窗

当有新的 service worker 等待安装时,会渲染 @theme/PwaReloadPopup 组件,提示用户刷新。你可以 swizzle 该组件,自定义 UI。该组件会接收 onReload 回调 props,点击"刷新"按钮时应调用此回调,通知 service worker 安装新 worker 并刷新页面。

默认主题已实现刷新弹窗,使用 Infima Alerts

刷新过程演示。窗口右下角弹出提示&quot;有新内容可用&quot;,点击&quot;刷新&quot;按钮后,页面主标题从&quot;Introduction&quot;变为&quot;PWA :))&quot;。

你的组件可以返回 null,但不推荐这样做,否则用户无法获取最新内容。