Create React App自定义ServiceWorker编译报错:所有标识符未定义
I've run into this exact issue before—Create React App's default build pipeline treats every .js file in the src/ directory as application code, so it's transpiling your sw-custom.js with Babel and Webpack, which breaks the Service Worker-specific environment. Here's how to fix it step by step:
Step 1: Move Your Custom Service Worker Out of src/
CRA doesn't process files outside the src/ directory (no extra configuration needed here).
- Move
sw-custom.jsfromsrc/sw-custom.jsto your project's root directory (same level aspackage.json). - Update your
react-build.jsto point to the new path:swSrc: './sw-custom.js', // Changed from 'src/sw-custom.js'
Step 2: Fix Invalid Code in Your Service Worker
Your current sw-custom.js has a critical error that will throw undefined errors even after fixing the build issue:
window.location.reload()doesn't exist in the Service Worker context—there's nowindowobject available here.
Replace that lifecycle code with proper Service Worker handling:
self.addEventListener('install', (event) => { self.skipWaiting(); console.log('Service Worker installed'); }); self.addEventListener('activate', (event) => { // Take control of all open clients immediately event.waitUntil(clients.claim()); // Optional: Notify clients to refresh for latest content clients.matchAll({ type: 'window' }).then(clients => { clients.forEach(client => { client.postMessage({ type: 'SW_UPDATED' }); }); }); });
You can add code in your React app to listen for this message and trigger a reload if needed:
// In your main App component or index.js if ('serviceWorker' in navigator) { navigator.serviceWorker.addEventListener('message', (event) => { if (event.data.type === 'SW_UPDATED') { if (confirm('New version available! Refresh to update?')) { window.location.reload(); } } }); }
Step 3: Update the Service Worker Registration Path
Your CRA-generated registration file points to service-worker.js, but your custom build script outputs to sw.js. Update the register function:
// In CRA's service worker registration file const swUrl = `${process.env.PUBLIC_URL}/sw.js`; // Changed from '/service-worker.js'
Step 4: Verify Your Build Script
Make sure your package.json runs the React build first, then injects the manifest:
"scripts": { "build": "react-scripts build && node react-build.js", // ... other scripts }
Final Corrected sw-custom.js
Here's the full fixed version of your custom Service Worker:
if ('function' === typeof importScripts) { importScripts( 'https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js' ); // Global workbox if (workbox) { console.log('Workbox is loaded'); // Disable logging workbox.setConfig({ debug: false }); self.addEventListener('install', (event) => { self.skipWaiting(); console.log('Service Worker installed'); }); self.addEventListener('activate', (event) => { event.waitUntil(clients.claim()); clients.matchAll({ type: 'window' }).then(clients => { clients.forEach(client => { client.postMessage({ type: 'SW_UPDATED' }); }); }); console.log('Service Worker activated and controlling clients'); }); // Manual injection point for manifest files. // All assets under build/ and 5MB sizes are precached. workbox.precaching.precacheAndRoute([]); // Font caching workbox.routing.registerRoute( new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'), workbox.strategies.cacheFirst({ cacheName: 'googleapis', plugins: [ new workbox.expiration.Plugin({ maxEntries: 30, }), ], }) ); // Image caching workbox.routing.registerRoute( /\.(?:png|gif|jpg|jpeg|svg)$/, workbox.strategies.cacheFirst({ cacheName: 'images', plugins: [ new workbox.expiration.Plugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days }), ], }) ); // JS, CSS caching workbox.routing.registerRoute( /\.(?:js|css)$/, workbox.strategies.staleWhileRevalidate({ cacheName: 'static-resources', plugins: [ new workbox.expiration.Plugin({ maxEntries: 60, maxAgeSeconds: 20 * 24 * 60 * 60, // 20 Days }), ], }) ); } else { console.error('Workbox could not be loaded. No offline support'); } }
These changes will prevent CRA from compiling your Service Worker code, fix the invalid window reference, and ensure your custom Service Worker is registered correctly.
内容的提问来源于stack exchange,提问作者Sean Moody

