跳到主要内容

📦 plugin-pwa

使用 Workbox 为您的站点添加 PWA 支持的 Docusaurus 插件。此插件仅在生产构建中生成 Service Worker,并允许您创建完全符合 PWA 标准的文档站点,支持离线和安装功能。

安装

npm install --save @docusaurus/plugin-pwa

配置

./static/manifest.json 创建一个 PWA 清单

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',
},
{
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',
},
],
},
],
],
};

渐进式 Web 应用

仅仅安装服务工作者是不够的,要使您的应用成为 PWA。您至少需要包含一个 Web 应用清单,并在 <head> 中添加正确的标签(选项 > pwaHead)。

部署后,您可以使用 Lighthouse 对您的站点进行审核。

关于使您的站点成为 PWA 的更详细清单,请参考 PWA 清单

应用安装支持

如果您的浏览器支持,您应该能够将 Docusaurus 站点安装为应用。

安装过程的屏幕录制。在浏览器地址栏中出现一个按钮,点击时会显示&quot;是否安装此应用?&quot;的对话框。点击&quot;安装&quot;按钮后,在操作系统中打开一个新应用,并转到 Docusaurus 主页。

备注

应用安装需要 HTTPS 协议和有效的清单。

离线模式(预缓存)

我们通过使用服务工作者预缓存,使用户能够离线浏览 Docusaurus 站点。

workbox-precaching 页面解释了这个概念:

服务工作者的一个特性是在安装服务工作者时将一组文件保存到缓存中。这通常被称为"预缓存",因为您是在服务工作者被使用之前缓存内容。

这样做的主要原因是它给开发者提供了对缓存的控制,这意味着他们可以确定文件何时以及缓存多长时间,并且可以在不访问网络的情况下将其提供给浏览器,这意味着可以用它来创建离线工作的 Web 应用。

Workbox 通过简化 API 并确保资源高效下载,减轻了预缓存的大部分繁重工作。

默认情况下,当站点作为应用安装时,离线模式处于启用状态。有关详细信息,请参见 offlineModeActivationStrategies 选项。

站点预缓存后,服务工作者将为后续访问提供缓存的响应。当部署新的构建并伴随新的服务工作者时,新的服务工作者将开始安装并最终进入等待状态。在等待状态期间,将显示重新加载弹出窗口,并要求用户重新加载页面以获取新内容。在用户清除应用缓存或点击弹出窗口上的 重新加载 按钮之前,服务工作者将继续提供旧内容。

注意

离线模式/预缓存需要提前下载站点的所有静态资源,可能会消耗不必要的带宽。对于所有类型的站点,激活它可能并不是一个好主意。

Options

debug

  • Type: boolean
  • Default: false

Turn debug mode on:

  • Workbox logs
  • Additional Docusaurus logs
  • Unoptimized SW file output
  • Source maps

offlineModeActivationStrategies

  • Type: ('appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always')[]
  • Default: ['appInstalled', 'queryString', 'standalone']

Strategies used to turn the offline mode on:

  • appInstalled: activates for users having installed the site as an app (not 100% reliable)
  • standalone: activates for users running the app as standalone (often the case once a PWA is installed)
  • queryString: activates if queryString contains offlineMode=true (convenient for PWA debugging)
  • mobile: activates for mobile users (width <= 996px)
  • saveData: activates for users with navigator.connection.saveData === true
  • always: activates for all users
注意

Use this carefully: some users may not like to be forced to use the offline mode.

危险

It is not possible to detect if a page is rendered as a PWA in a reliable manner.

The appinstalled event has been removed from the specification, and the navigator.getInstalledRelatedApps() API is only supported in recent Chrome versions and require related_applications declared in the manifest.

The standalone strategy is a nice fallback to activate the offline mode (at least when running the installed app).

injectManifestConfig

Workbox options to pass to workbox.injectManifest(). This gives you control over which assets will be precached, and be available offline.

  • Type: InjectManifestOptions
  • Default: {}
docusaurus.config.js
export default {
plugins: [
[
'@docusaurus/plugin-pwa',
{
injectManifestConfig: {
manifestTransforms: [
//...
],
modifyURLPrefix: {
//...
},
// We already add regular static assets (HTML, images...) to be available offline
// You can add more files according to your needs
globPatterns: ['**/*.{pdf,docx,xlsx}'],
// ...
},
},
],
],
};

pwaHead

  • Type: ({ tagName: string; [attributeName: string]: string })[]
  • Default: []

包含 tagName 和属性键值对的对象数组,用于注入 <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

  • Type: string | undefined
  • Default: undefined

对于额外的 Workbox 规则很有用。您可以在这里执行服务工作者可以做的任何操作,并充分利用 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

  • Type: string | false
  • Default: 'docusaurus-plugin-pwa/src/registerSW.js'

在 Docusaurus 应用之前添加一个入口,以便在应用运行之前进行注册。默认的 registerSW.js 文件对于简单注册已经足够。

传递 false 将完全禁用注册。

Manifest example

Docusaurus 站点清单可以作为参考:

{
"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"
}
]
}

Customizing reload popup

当新的服务工作者正在等待安装,并且我们向用户建议重新加载时,将渲染 @theme/PwaReloadPopup 组件。您可以交换此组件并实现自己的 UI。它将接收 onReload 回调作为 props,当点击 重新加载 按钮时应调用该回调。这将告诉服务工作者安装等待的服务工作者并重新加载页面。

默认主题包含重新加载弹出窗口的实现,并使用 Infima 警报

重新加载过程的屏幕录制。窗口右下角显示一个警报框,显示&quot;新内容可用&quot;。点击&quot;刷新&quot;按钮后,页面主标题从&quot;介绍&quot;变为&quot;PWA :))&quot;。

您的组件可以渲染 null,但不建议这样做:用户将无法获取最新内容。