在 React 项目中使用 TypeScript 编写 Service Worker 的完整方案如下:
📝 实现步骤
1. 项目初始化
确保你的 React 项目已支持 TypeScript(通过 create-react-app
或自定义配置)
bash
npx create-react-app my-app --template typescript
cd my-app
npm install @types/service_worker_api --save-dev
2. 创建 Service Worker 文件
新建 src/sw.ts
:
typescript
// src/sw.ts
interface DomainUpdateEvent extends ExtendableEvent {
detail: {
domains: string[];
};
}
const ALLOWED_DOMAINS: string[] = ['api.example.com'];
self.addEventListener('fetch', (event) => {
const requestURL = new URL(event.request.url);
const requestedDomain = requestURL.hostname;
if (ALLOWED_DOMAINS.includes(requestedDomain)) {
console.log(`[SW] 允许请求: ${event.request.url}`);
// 示例:添加请求头
const modifiedHeaders = new Headers(event.request.headers);
modifiedHeaders.append('X-SW-Optimized', 'true');
event.respondWith(
fetch(event.request, {
headers: modifiedHeaders
})
);
}
});
// 动态更新白名单
self.addEventListener('message', (e: DomainUpdateEvent) => {
if (e.detail?.domains) {
ALLOWED_DOMAINS.push(...e.detail.domains);
console.log('[SW] 更新白名单:', ALLOWED_DOMAINS);
}
});
3. 配置编译输出
修改 tsconfig.json
:
json
{
"compilerOptions": {
"outDir": "build/sw",
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/sw.ts"]
}
4. 注册 Service Worker
在 src/App.tsx
中注册:
typescript
// src/App.tsx
import { useEffect } from 'react';
function App() {
useEffect(() => {
if ('serviceWorker' in navigator) {
const registerSW = async () => {
try {
const registration = await navigator.serviceWorker.register(
process.env.PUBLIC_URL + '/sw.js'
);
console.log('SW 注册成功:', registration);
} catch (err) {
console.error('SW 注册失败:', err);
}
};
// 开发环境热更新
if (process.env.NODE_ENV === 'development') {
const updateSW = () => {
navigator.serviceWorker.getRegistrations().then(registrations => {
registrations.forEach(registration => registration.update());
});
};
setInterval(updateSW, 60000); // 每分钟检查更新
}
registerSW();
}
}, []);
return <div>App Content</div>;
}
export default App;
5. 配置构建脚本
在 package.json
中添加构建命令:
json
{
"scripts": {
"build:sw": "tsc --project tsconfig.json",
"build": "npm run build:sw && react-scripts build",
"start": "react-scripts start && npm run build:sw -- --watch"
}
}
🛠️ 高级技巧
-
缓存策略集成
添加 Workbox 支持:
bashnpm install workbox-build
创建
workbox-config.js
:javascriptmodule.exports = { globDirectory: 'build/', globPatterns: ['**/*.{js,css,html,png}'], swDest: 'build/sw.js', clientsClaim: true, skipWaiting: true };
修改构建脚本:
json{ "scripts": { "build": "react-scripts build && workbox injectManifest workbox-config.js" } }
-
动态配置更新
通过网页发送消息更新配置:
typescript// 在组件中 const updateSWConfig = () => { if ('serviceWorker' in navigator) { navigator.serviceWorker.controller?.postMessage({ type: 'UPDATE_DOMAINS', domains: ['new-domain.com'] }); } };
-
调试支持
在
src/sw.ts
中添加调试开关:typescriptconst DEBUG_MODE = process.env.NODE_ENV === 'development'; if (DEBUG_MODE) { self.addEventListener('activate', (event) => { console.log('[SW] 激活事件:', event); }); }
⚠️ 注意事项
-
作用域限制
确保 Service Worker 文件位于网站根目录或子目录,且作用域能覆盖目标请求路径。
-
HTTPS 要求
生产环境必须使用 HTTPS(本地开发可通过
localhost
使用)。 -
更新机制
修改 Service Worker 后需重新编译并刷新页面,或调用
registration.update()
。 -
文件哈希
建议为编译后的 Service Worker 文件添加哈希值(如
sw.[hash].js
)以避免缓存问题。