Service Worker 需手动注册、监听fetch并管理缓存策略,强制HTTPS(本地除外),常见错误包括MIME类型错误、scope缺失、未预缓存HTML等;离线能力取决于具体缓存逻辑实现。
Service Worker 是浏览器后台运行的脚本,能拦截网络请求、缓存资源、实现离线访问——但它不是“开箱即用”的离线开关,必须手动注册、监听 fetch 事件、并主动管理缓存策略。
浏览器强制要求:线上环境必须在 HTTPS *册 serviceWorker,否则 navigator.serviceWorker.register() 会直接失败并抛出 TypeError。localhost 和 127.0.0.1 被豁免,可本地调试。
常见错误现象:
Uncaught DOMException: Failed to register a ServiceWorker: The script has an unsupported MIME type ('text/html') —— 检查服务器是否返回了正确的 Content-Type: text/javascript
Uncaught (in promise) DOMException: Registration failed – no scope provided —— register() 的第二个参数 {scope: '...'} 缺失或路径不合法(scope 不能高于 service worker 文件所在目录)注册成功
≠ 自动离线。Service Worker 默认不缓存任何请求,你必须在 SW 脚本中监听 fetch 事件,并显式调用 caches.match() 或 fetch()。
典型缓存策略示例(优先读缓存,缓存未命中再发网络请求):
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
if (response) return response;
return fetch(event.request);
})
);
});
注意点:
caches.open('v1') 必须先调用,否则 caches.match() 返回 undefined
install 事件中预缓存,避免首次 fetch 时缓存为空fetch() 请求默认不带 cookies,如需认证,得加 {credentials: 'include'}
新版本 SW 文件部署后,旧版仍会持续控制页面,直到所有打开的页面关闭、或调用 skipWaiting() + clients.claim() 强制接管。
常见陷阱:
fetch 仍走旧逻辑 —— 检查 DevTools > Application > Service Workers 是否显示 “Waiting” 状态'v1'),导致新 SW 读的是旧缓存 —— 每次变更缓存策略必须改 cacheNameactivate 事件中遍历 caches.keys() 删除非当前版本缓存很多开发者以为注册了 SW 就能离线,结果发现 HTML 页面打不开——因为根路径 / 的 HTML 没被预缓存,而 SW 的 fetch 事件里又没对 HTML 做 fallback 处理。
实操建议:
install 阶段用 caches.addAll(['/', '/index.html', '/app.js']) 预加载关键资源/offline.html(用 Response.redirect() 或构造 new Response(htmlString, {headers}))stale-while-revalidate 策略,在 fetch 中判断 event.request.destination === 'json' 分流处理离线能力不是靠 Service Worker 自身,而是靠你写的每一条 caches.put()、每一次 event.respondWith() 决定的。最容易被跳过的环节是缓存命名更新和 activate 清理,这两步漏掉,离线行为就会不可预测。