如何在Gulp的Workbox Service Worker生成中添加外部数据源?
Great question! The issue you’re hitting is that workbox.generateSW() is built for caching local static assets—its globPatterns only targets files on your filesystem, not external URLs like Google Fonts. Also, swSrc doesn’t work with generateSW() because this method creates the entire service worker from scratch, rather than injecting logic into a custom template.
You don’t need a separate service worker to handle external resources. Here are the two best solutions, with the first being the most flexible:
1. Switch to workbox.injectManifest() (Recommended)
injectManifest() lets you use a custom service worker template where you can add rules for external resources, while still letting Workbox automatically handle caching your local assets. Here’s how to set it up:
Step 1: Create a Custom Service Worker Template
Make a new file (e.g., src/sw-template.js) with your custom logic for external resources. For Google Fonts, we’ll use Workbox’s routing strategies to cache stylesheets and font files appropriately:
// src/sw-template.js import { registerRoute } from 'workbox-routing'; import { CacheFirst, StaleWhileRevalidate } from 'workbox-strategies'; import { CacheableResponsePlugin } from 'workbox-cacheable-response'; // Cache Google Fonts stylesheets with a stale-while-revalidate strategy registerRoute( ({ url }) => url.origin === 'https://fonts.googleapis.com', new StaleWhileRevalidate({ cacheName: 'google-fonts-stylesheets', }) ); // Cache Google Fonts webfont files with a cache-first strategy (they rarely change) registerRoute( ({ url }) => url.origin === 'https://fonts.gstatic.com', new CacheFirst({ cacheName: 'google-fonts-webfonts', plugins: [ new CacheableResponsePlugin({ statuses: [0, 200], // Handle opaque responses from CDNs }), ], }) ); // Workbox will automatically inject your local asset manifest here self.__WB_MANIFEST;
Step 2: Update Your Gulp Task
Replace generateSW() with injectManifest() in your Gulp task, pointing to your new template:
gulp.task('generate-service-worker', () => { return workbox.injectManifest({ globDirectory: buildDir, globPatterns: ['**/*.{html,png,css,js,ico,eot,svg,ttf,woff,woff2,jpg,json}'], swSrc: 'src/sw-template.js', // Path to your custom template swDest: `${buildDir}/sw.js`, clientsClaim: true, skipWaiting: true }).then(() => { console.info('Service worker generation completed.'); }).catch((error) => { console.warn('Service worker generation failed: ' + error); }); });
This approach gives you full control over your service worker’s logic while still leveraging Workbox’s automatic local asset caching.
2. Use additionalManifestEntries (Limited Use Case)
If you really want to stick with generateSW(), you can manually add specific external URLs to the cache using additionalManifestEntries. However, this is less flexible because you have to list every URL explicitly and manage revision numbers manually:
gulp.task('generate-service-worker', () => { return workbox.generateSW({ globDirectory: buildDir, globPatterns: ['**/*.{html,png,css,js,ico,eot,svg,ttf,woff,woff2,jpg,json}'], swDest: `${buildDir}/sw.js`, clientsClaim: true, skipWaiting: true, additionalManifestEntries: [ { url: 'https://fonts.googleapis.com/css2?family=Roboto', revision: 'v1', // Update this whenever the font stylesheet changes }, { url: 'https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2', revision: 'v30', }, ] }).then(() => { console.info('Service worker generation completed.'); }).catch((error) => { console.warn('Service worker generation failed: ' + error); }); });
We don’t recommend this for Google Fonts because URLs can change, and maintaining this list is tedious.
Final Notes
You don’t need a separate service worker—injectManifest() lets you handle both local and external resources in one file. While you could reference Workbox’s Grunt build docs, the core approach (using injectManifest() for custom logic) is identical across build tools, so the Gulp solution above works perfectly.
内容的提问来源于stack exchange,提问作者André Kelling

