跳转至主内容
Version: 2.0.0-beta.5 🚧

📦 plugin-pwa

使用 Workbox 来添加 PWA 支持的 Docusaurus 插件。 此插件将仅在生产构建中生成 Service Worker,让您创建支持离线模式和安装的 PWA 文档站点。

安装#

npm install --save @docusaurus/plugin-pwa

配置#

./static/manifest.json 处新建 PWA Manifest

docusaurus.config.js 里简单配置 PWA,如下所示:

docusaurus.config.js
module.exports = {  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)',          },        ],      },    ],  ],};

渐进式网页应用#

安装 Service Worker 还不足以让您的应用程序成为渐进式 Web 应用(PWA)。 您至少需要先包含 Web App Manifest,并在 <head> 里填写正确的标签(设置 > pwaHead)。

部署后,您可使用 Lighthouse 来检查您网站的性能。

欲查看制作 PWA 的先决条件,请参阅 PWA 检查单

应用安装支持#

若您的浏览器支持,您将可以把 Docusaurus 安装为应用。

pwa_install.gif

note

安装应用需要 HTTPS 协议及有效的 Manifest。

离线模式(预缓存)#

我们通过 Service Worker 预缓存的方式支持用户离线访问 Docusaurus 站点。

预缓存是什么?#

Service Worker 的功能之一是在安装过程中保存一系列文件至缓存。 由于您在 Service Worker 使用前就已经开始缓存内容,此功能一般被称为“预缓存”。

使用此功能的主要原因是让开发者控制缓存,决定何时缓存、缓存时间长度及在离线时向浏览器提供内容,即创建离线网页应用。

Workbox 为您完成了预缓存期间的诸多复杂工作,简化了 API 的同时还确保能高效率地下载资源。

默认情况下,当网站作为应用程序安装时将默认启用离线模式。 请参阅 offlineModeActivationStrategies 选项以了解详情。

当网站预缓存完毕后,Service Worker 将为之后的请求提供缓存过的回应。 当新构建版本随着新 Service Worker 一起部署后,新版本将自动开始安装并变成等待状态。 在此期间,网站将弹出刷新弹窗来提示用户刷新页面以查看新内容。 除非用户清除应用程序缓存或点击弹窗的刷新按钮,否则 Service Worker 将一直提供旧内容。

注意

离线模式/预缓存需要提前下载网站上的所有静态资源,可能会导致不必要的流量消耗。 并非每个站点都有必要开启此选项。

选项#

调试#

  • 类型:boolean
  • 默认值:false

打开调试模式:

  • Workbox 日志
  • 额外的 Docusaurus 日志
  • 未优化的 SW 文件输出
  • Source Map

offlineModeActivationStrategies#

  • 类型:Array<'appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always'>
  • 默认值:['appInstalled','queryString','standalone']

开启离线模式的策略有:

  • appInstalled:在用户安装网站为应用程序时启用(并非百分百可靠)
  • standalone:在用户以独立模式运行应用程序时启用(通常在安装 PWA 后)
  • queryString:在 queryString 包含 offlineMode=true 后启用(通常用于 PWA 调试)
  • mobile:为手机用户启用(宽度 <= 940px)
  • saveData:为 navigator.connection.saveData === true 的用户启用
  • always:为所有用户启用
注意

小心使用此功能:部份用户可能不喜欢强制使用离线模式。

danger

我们无法非常可靠地检测 PWA。

技术规范中已经移除了 appinstalled 事件,而且只有新版本的 Chrome 支持 navigator.getInstalledRelatedApps() API,此时还需要在 Manifest 中声明 related_applications

standalone 策略是启用离线模式的优秀备选(至少在运行已安装应用时)。

injectManifestConfig#

传递至 workbox.injectManifest()Workbox 选项。 此选项让您筛选需要预缓存、且可用于离线的资源。

  • 类型:InjectManifestOptions
  • 默认值:{}
docusaurus.config.js
module.exports = {  plugins: [    [      '@docusaurus/plugin-pwa',      {        injectManifestConfig: {          manifestTransforms: [            //...          ],          modifyURLPrefix: {            //...          },          // 我们已添加了常见的静态资源(HTML、图像等)          // 您可以在此处按需添加文件          globPatterns: ['**/*.{pdf,docx,xlsx}'],          // ...        },      },    ],  ],};

reloadPopup#

  • 类型:string | false
  • 默认值:'@theme/PwaReloadPopup'

刷新弹窗组件的模块路径。 此弹窗将在等待安装新 Service Worker 前渲染,并提示用户刷新。

传递 false 参数将禁用此弹窗,但不推荐,因为用户可能没有办法获取最新内容。

您可使用自定义组件,只要其接受 onReload 属性(Prop)即可。 onReload 回调函数将在按下刷新按钮后被调用。 这将告诉 Service Worker 安装等待中的新版 Service Worker 并刷新页面。

interface PwaReloadPopupProps {  onReload: () => void;}

默认主题包含了使用 Infima Alerts 的刷新弹窗的默认实现。

pwa_reload.gif

pwaHead#

  • 类型:Array<{ tagName: string } & Record<string,string>>
  • 默认值:[]

包含 tagName 的对象数组及注入 <head> 标签的属性键值对。 技术上说,您可以透过此选项注入任意头部标签,但最好放入能让您的网站兼容 PWA 的标签。 下列是让您应用程序完全兼容的标签列表:

module.exports = {  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'

在 Docusaurus 应用前添加入口,让注册在应用运行前发生。 默认的 registerSW.js 文件足以进行简单注册。

传递 false 参数将完全关闭注册功能。

清单示例#

Docusaurus 网站的 Manifest 可以给您一些启发:

{  "name": "Docusaurus v2",  "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"    }  ]}