工作区-sw

workbox-sw 模块提供了一种极其简单的方法来启动和运行 Workbox 模块,简化了 Workbox 模块的加载,并且提供了一些简单的辅助方法。

您可以通过我们的 CDN 使用 workbox-sw,也可以将其用于您自己的服务器上的一组工作箱文件。

通过 CDN 使用 Workbox SW

要开始使用此模块,最简单的方法是通过 CDN。您只需将以下内容添加到 Service Worker:

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

这样,您的 Service Worker 中将会有 workbox 命名空间,该命名空间将提供对所有 Workbox 模块的访问权限。

workbox.precaching.*
workbox.routing.*
etc

当您开始使用其他模块时,就会发现一些神奇的功能。

当您首次引用某个模块时,workbox-sw 会检测到这种情况并加载该模块,然后再使其可用。您可以在开发者工具的“Network”标签页中看到发生这种情况。

在开发者工具中加载 Workbox 库

这些文件将由浏览器缓存,以供日后离线使用。

使用本地 Workbox 文件,而非 CDN

如果您不想使用 CDN,也可以轻松切换到托管在您自己的网域上的 Workbox 文件。

最简单的方法是通过 workbox-clicopyLibraries 命令获取文件,然后通过 modulePathPrefix 配置选项告知 workbox-sw 在哪里可以找到这些文件。

如果将文件放在 /third_party/workbox-vX.Y.Z/ 下,可按如下方式使用它们:

importScripts('/third_party/workbox-vX.Y.Z/workbox-sw.js');

workbox.setConfig({
  modulePathPrefix: '/third_party/workbox-vX.Y.Z/',
});

避免异步导入

实际上,首次加载新模块涉及使用相应 JavaScript 文件的路径(托管在 CDN 上,或通过本地网址)调用 importScripts()。无论哪种情况,都存在一个重要的限制:对 importScripts() 的隐式调用只能在 Service Worker 的 install 处理程序内部进行,或者只能在 Service Worker 脚本的同步初始执行期间进行。

为避免违反此限制,最佳实践是在任何事件处理脚本或异步函数之外引用各种 workbox.* 命名空间。

例如,以下顶级 Service Worker 代码没有问题:

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

// This will work!
workbox.routing.registerRoute(
  ({request}) => request.destination === 'image',
  new workbox.strategies.CacheFirst()
);

但是,如果您未在 Service Worker 的其他位置引用 workbox.strategies,以下代码可能会出现问题:

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

self.addEventListener('fetch', event => {
  if (event.request.url.endsWith('.png')) {
    // Oops! This causes workbox-strategies.js to be imported inside a fetch handler,
    // outside of the initial, synchronous service worker execution.
    const cacheFirst = new workbox.strategies.CacheFirst();
    event.respondWith(cacheFirst.handle({request: event.request}));
  }
});

如果您需要编写会违反此限制的代码,可以使用 workbox.loadModule() 方法在事件处理脚本之外显式触发 importScripts() 调用:

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

// This will trigger the importScripts() for workbox.strategies and its dependencies:
workbox.loadModule('workbox-strategies');

self.addEventListener('fetch', event => {
  if (event.request.url.endsWith('.png')) {
    // Referencing workbox.strategies will now work as expected.
    const cacheFirst = new workbox.strategies.CacheFirst();
    event.respondWith(cacheFirst.handle({request: event.request}));
  }
});

或者,您也可以在事件处理脚本之外创建对相关命名空间的引用,稍后使用该引用:

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

// This will trigger the importScripts() for workbox.strategies and its dependencies:
const {strategies} = workbox;

self.addEventListener('fetch', event => {
  if (event.request.url.endsWith('.png')) {
    // Using the previously-initialized strategies will work as expected.
    const cacheFirst = new strategies.CacheFirst();
    event.respondWith(cacheFirst.handle({request: event.request}));
  }
});

强制使用调试 build 或正式版 build

所有 Workbox 模块都包含两个 build:一个是调试 build(包含日志记录和额外的类型检查),另一个是去除日志记录和类型检查的正式版 build。

默认情况下,workbox-sw 将针对 localhost 上的网站使用调试 build;但对于任何其他来源,则使用正式版 build。

如果要强制使用调试 build 或正式版 build,您可以设置 debug 配置选项:

workbox.setConfig({
  debug: true,
});

使用 import 语句转换代码以使用 workbox-sw

使用 workbox-sw 加载 Workbox 时,所有 Workbox 软件包都通过全局 workbox.* 命名空间访问。

如果您有使用 import 语句的代码示例,并且想要将其转换为使用 workbox-sw,则只需加载 workbox-sw 并将所有 import 语句替换为引用全局命名空间中这些模块的局部变量即可。

这是因为发布到 npm 的每个 Workbox Service Worker 软件包都可以通过名称的 camelCase 版本在全局 workbox 命名空间上使用(例如,从 workbox-precaching npm 软件包导出的所有模块都可以在 workbox.precaching.* 上找到)。此外,从 workbox-background-sync npm 软件包导出的所有模块都可以在 workbox.backgroundSync.* 上找到。

例如,以下代码使用 import 语句来引用 Workbox 模块:

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {CacheableResponse} from 'workbox-cacheable-response';

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({
    plugins: [new CacheableResponsePlugin({statuses: [0, 200]})],
  })
);

以下是使用 workbox-sw 重写的相同代码(请注意,只有 import 语句发生了变化,逻辑没有发生变化):

importScripts(
  'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
);

const {registerRoute} = workbox.routing;
const {CacheFirst} = workbox.strategies;
const {CacheableResponse} = workbox.cacheableResponse;

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({
    plugins: [new CacheableResponsePlugin({statuses: [0, 200]})],
  })
);