乐闻世界logo
搜索文章和话题

Service Worker 中的 Workbox 是什么?它提供了哪些功能?

3月6日 21:56

Workbox 详解

Workbox 是 Google 开发的一套 JavaScript 库,用于简化 Service Worker 的开发,提供了一系列强大的缓存策略和工具。

Workbox 简介

什么是 Workbox

Workbox 是一套模块化的库,帮助开发者:

  • 简化 Service Worker 编写
  • 提供预置的缓存策略
  • 自动生成 Service Worker
  • 提供开发调试工具
bash
# 安装 Workbox npm install workbox-sw workbox-cli --save-dev # 或使用 CDN importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.5.4/workbox-sw.js');

核心模块

模块功能
workbox-routing请求路由匹配
workbox-strategies缓存策略
workbox-precaching预缓存
workbox-cacheable-response缓存响应管理
workbox-expiration缓存过期控制
workbox-background-sync后台同步
workbox-google-analyticsGoogle Analytics 离线支持

基础使用

1. 使用 CDN 引入

javascript
// sw.js importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.5.4/workbox-sw.js'); // Workbox 会自动加载核心模块 workbox.setConfig({ debug: true // 开发模式 }); // 使用路由和策略 workbox.routing.registerRoute( ({ request }) => request.destination === 'image', new workbox.strategies.CacheFirst() );

2. 使用 npm 和构建工具

javascript
// sw.js import { precacheAndRoute } from 'workbox-precaching'; import { registerRoute } from 'workbox-routing'; import { CacheFirst, NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies'; import { ExpirationPlugin } from 'workbox-expiration'; // 预缓存 precacheAndRoute(self.__WB_MANIFEST); // 图片使用 Cache First 策略 registerRoute( ({ request }) => request.destination === 'image', new CacheFirst({ cacheName: 'images', plugins: [ new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 // 30天 }) ] }) );

核心功能详解

1. 路由(Routing)

javascript
import { registerRoute } from 'workbox-routing'; // 方式1:字符串匹配 registerRoute( '/api/users', new NetworkFirst() ); // 方式2:正则匹配 registerRoute( new RegExp('/api/.*'), new NetworkFirst() ); // 方式3:回调函数匹配 registerRoute( ({ url, request, event }) => { return url.pathname.startsWith('/api/') && request.method === 'GET'; }, new NetworkFirst() ); // 方式4:使用 Route 类 import { Route } from 'workbox-routing'; const apiRoute = new Route( ({ url }) => url.pathname.startsWith('/api/'), new NetworkFirst() ); registerRoute(apiRoute);

2. 缓存策略(Strategies)

javascript
import { CacheFirst, NetworkFirst, StaleWhileRevalidate, NetworkOnly, CacheOnly } from 'workbox-strategies'; // Cache First - 缓存优先 registerRoute( ({ request }) => request.destination === 'style' || request.destination === 'script', new CacheFirst({ cacheName: 'static-resources' }) ); // Network First - 网络优先 registerRoute( ({ url }) => url.pathname.startsWith('/api/'), new NetworkFirst({ cacheName: 'api-cache', plugins: [ new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 5 * 60 // 5分钟 }) ] }) ); // Stale While Revalidate - 过期时重新验证 registerRoute( ({ request }) => request.destination === 'image', new StaleWhileRevalidate({ cacheName: 'images', plugins: [ new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }) ] }) );

3. 预缓存(Precaching)

javascript
import { precacheAndRoute, cleanupOutdatedCaches } from 'workbox-precaching'; // 方式1:手动指定资源 precacheAndRoute([ { url: '/index.html', revision: '1.0.0' }, { url: '/styles.css', revision: '1.0.0' }, { url: '/app.js', revision: '1.0.0' } ]); // 方式2:使用构建工具生成的清单 // webpack 配置 const { InjectManifest } = require('workbox-webpack-plugin'); module.exports = { plugins: [ new InjectManifest({ swSrc: './src/sw.js', swDest: 'sw.js' }) ] }; // sw.js 中使用 precacheAndRoute(self.__WB_MANIFEST); // 清理过期缓存 cleanupOutdatedCaches();

4. 缓存过期控制

javascript
import { ExpirationPlugin } from 'workbox-expiration'; registerRoute( ({ request }) => request.destination === 'image', new CacheFirst({ cacheName: 'images', plugins: [ new ExpirationPlugin({ maxEntries: 50, // 最大条目数 maxAgeSeconds: 30 * 24 * 60 * 60, // 最大存活时间(30天) purgeOnQuotaError: true // 存储不足时自动清理 }) ] }) );

5. 缓存响应管理

javascript
import { CacheableResponsePlugin } from 'workbox-cacheable-response'; registerRoute( ({ url }) => url.pathname.startsWith('/api/'), new NetworkFirst({ cacheName: 'api-cache', plugins: [ new CacheableResponsePlugin({ statuses: [0, 200], // 只缓存状态码 0 和 200 headers: { 'X-Cache-Allowed': 'true' // 只缓存包含特定头的响应 } }) ] }) );

6. 后台同步

javascript
import { BackgroundSyncPlugin } from 'workbox-background-sync'; // 创建后台同步队列 const bgSyncPlugin = new BackgroundSyncPlugin('api-queue', { maxRetentionTime: 24 * 60 // 24小时 }); registerRoute( ({ url }) => url.pathname.startsWith('/api/'), new NetworkFirst({ plugins: [bgSyncPlugin] }), 'POST' );

7. 范围请求支持

javascript
import { RangeRequestsPlugin } from 'workbox-range-requests'; registerRoute( ({ url }) => url.pathname.endsWith('.mp4'), new CacheFirst({ cacheName: 'videos', plugins: [ new RangeRequestsPlugin() // 支持视频范围请求 ] }) );

高级用法

自定义策略

javascript
import { Strategy } from 'workbox-strategies'; class CustomStrategy extends Strategy { async _handle(request, handler) { // 尝试从缓存获取 const cachedResponse = await handler.cacheMatch(request); if (cachedResponse) { // 在后台更新缓存 handler.fetchAndCachePut(request).catch(() => {}); return cachedResponse; } // 缓存未命中,请求网络 return handler.fetchAndCachePut(request); } } registerRoute( '/custom-route', new CustomStrategy() );

插件开发

javascript
// 自定义日志插件 const loggingPlugin = { cacheWillUpdate: async ({ request, response }) => { console.log(`缓存更新: ${request.url}`); return response; }, cacheDidUpdate: async ({ request, cacheName }) => { console.log(`缓存已更新: ${request.url} in ${cacheName}`); }, fetchDidFail: async ({ request, error }) => { console.error(`请求失败: ${request.url}`, error); } }; registerRoute( '/api/', new NetworkFirst({ plugins: [loggingPlugin] }) );

运行时缓存

javascript
import { warmStrategyCache } from 'workbox-recipes'; // 预热缓存 warmStrategyCache({ urls: ['/about', '/contact'], strategy: new StaleWhileRevalidate({ cacheName: 'pages' }) }); // 离线回退 import { offlineFallback } from 'workbox-recipes'; offlineFallback({ pageFallback: '/offline.html', imageFallback: '/images/offline.png', fontFallback: false });

配置选项

全局配置

javascript
import { setConfig } from 'workbox-core'; setConfig({ debug: process.env.NODE_ENV === 'development', logger: customLogger });

日志级别

javascript
import { setLogLevel, LOG_LEVELS } from 'workbox-core'; setLogLevel(LOG_LEVELS.debug); // debug, warn, error, silent

与构建工具集成

Webpack

javascript
// webpack.config.js const { GenerateSW, InjectManifest } = require('workbox-webpack-plugin'); module.exports = { plugins: [ // 自动生成 Service Worker new GenerateSW({ clientsClaim: true, skipWaiting: true, runtimeCaching: [ { urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/, handler: 'CacheFirst', options: { cacheName: 'images', expiration: { maxEntries: 60 } } } ] }) // 或注入到现有 Service Worker // new InjectManifest({ // swSrc: './src/sw.js', // swDest: 'sw.js' // }) ] };

Vite

javascript
// vite.config.js import { VitePWA } from 'vite-plugin-pwa'; export default { plugins: [ VitePWA({ workbox: { runtimeCaching: [ { urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/, handler: 'CacheFirst', options: { cacheName: 'images' } } ] } }) ] };

Workbox vs 原生 Service Worker

特性Workbox原生 Service Worker
学习曲线
代码量
缓存策略预置多种需手动实现
调试工具完善基础
灵活性极高
包大小增加约 20-50KB无额外开销

最佳实践

  1. 选择合适的策略:根据资源类型选择最佳缓存策略
  2. 设置缓存限制:使用 ExpirationPlugin 防止存储溢出
  3. 版本控制:使用预缓存时正确设置 revision
  4. 错误处理:添加适当的错误处理和降级方案
  5. 性能优化:避免缓存过多数据,定期清理
标签:Service Worker