service worker 无原生黑白名单机制,需在 fetch 事件中手动判断 url 和 request.destination 等属性实现过滤;作用域由注册时 scope 参数限定,白名单缓存可信静态资源,黑名单排除跨域、api、导航等请求,推荐使用 workbox 简化策略。

Service Worker 本身不提供“路由白名单/黑名单”的原生概念,它没有内置的黑白名单机制。所谓白名单或黑名单,其实是开发者在 fetch 事件中通过逻辑判断请求 URL 或 request.destination 等属性,决定是否拦截、缓存或放行——本质是手动实现的过滤策略。
配置的关键不在声明式规则,而在 self.addEventListener('fetch', ...) 中写对匹配逻辑,并配合 Workbox(推荐)或原生 Cache API 实现精准控制。
✅ 明确作用域:先设好 Service Worker 的生效范围
注册时用 scope 参数限定影响区域,这是最基础的“白名单”边界:
// 页面中注册
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', { scope: '/' })
.then(reg => console.log('SW 生效于', reg.scope));
}
-
scope: '/'→ 拦截整个站点所有请求(默认) -
scope: '/app/'→ 只影响/app/下的页面和资源
⚠️ 注意:sw.js文件必须位于scope路径下(如scope: '/app/',则sw.js得放在/app/sw.js)
✅ 白名单:只缓存你信任的资源路径
用正则或函数精准匹配,避免宽泛通配:
// ✅ 推荐:只缓存自己域名下的关键静态资源
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// 白名单条件:同源 + 路径在指定前缀内 + 非导航请求(避免缓存 HTML 导致离线跳转异常)
if (
url.origin === location.origin &&
/\.(js|css|html|woff2|png|jpg|svg)$/.test(url.pathname) &&
event.request.destination !== 'document'
) {
event.respondWith(
caches.match(event.request).then(res => res || fetch(event.request))
);
}
});
? 补充:Workbox 中更简洁:
Java JDK 25下载Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
import { registerRoute } from 'workbox-routing'; import { CacheFirst } from 'workbox-strategies';
// 只缓存 /static/ 和 /assets/ 下的图片与字体 registerRoute( ({ url }) => url.origin === location.origin && (/^\/(static|assets)\//.test(url.pathname) && ['image', 'font'].includes(event.request.destination)), new CacheFirst() );
---
### ❌ 黑名单:明确排除不该缓存的请求
常见需排除的类型:
- 跨域请求(第三方 API、CDN 资源)
- 浏览器导航请求(`destination === 'document'`,HTML 页面)——除非你做完整离线 SPA
- 特定后缀或路径(如 `/api/`, `/auth/`, `/metrics/`)
- 非 GET 请求(POST/PUT/DELETE 一般不缓存)
```js
// ✅ 在 fetch 中主动跳过黑名单请求
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// 黑名单:跨域、API 路径、非 GET、导航请求
if (
url.origin !== location.origin ||
url.pathname.startsWith('/api/') ||
url.pathname.startsWith('/auth/') ||
event.request.method !== 'GET' ||
event.request.destination === 'document'
) {
return; // 不拦截,走浏览器默认网络逻辑
}
event.respondWith(
caches.match(event.request).then(r => r || fetch(event.request))
);
});
? 提示:Workbox 提供
setCatchHandler处理未命中缓存的请求,但“不拦截”比“拦截后再放行”更轻量,优先用条件跳过。
⚠️ 特别注意:别误伤这些请求
以下情况容易被错误纳入缓存,引发问题:
-
<script src="https://cdn.jsdelivr.net/..."></script>→ 跨域脚本,缓存会失败或被 CORS 拒绝 -
fetch('https://third-party.com/data')→ 同样跨域,Service Worker 拦截后无法读取响应(除非对方配了Access-Control-Allow-Origin) -
<img src="data:image/...">或blob:URL →request.destination === 'image'但无有效 URL,匹配逻辑要加 guard -
<link rel="manifest">、/robots.txt、/favicon.ico→ 这些虽同源,但通常无需缓存,可单独排除
✅ 补充:用 Workbox 简化黑白名单管理
如果你用 Workbox(强烈推荐用于生产),可组合使用:
-
registerRoute()+ 正则/函数做路径白名单 -
skipWaiting()+clientsClaim()确保新缓存立即生效 -
cleanupOutdatedCaches()自动清理旧版本缓存
示例:只缓存静态资源,排除所有 API 和跨域请求
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst } from 'workbox-strategies';
// ✅ 白名单:静态资源走 CacheFirst
registerRoute(
({ request, url }) =>
request.destination === 'script' ||
request.destination === 'style' ||
request.destination === 'font' ||
(url.origin === self.location.origin && /\.(png|jpg|gif|webp|svg)$/.test(url.pathname)),
new CacheFirst()
);
// ✅ API 请求走 NetworkFirst(不进白名单缓存,但可运行时缓存)
registerRoute(
({ url }) => url.origin === 'https://api.example.com' && url.pathname.startsWith('/v1/'),
new NetworkFirst()
);
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











