Service Worker注册失败主因是环境或时机问题:非HTTPS(localhost除外)、sw.js路径404、注册过早;需确保安全上下文、load后注册、scope覆盖目标路径,并验证sw.js可访问及Content-Type正确。
Service Worker 注册失败,八成不是代码写错了,而是环境或时机没对——HTTPS 缺失、sw.js 路径 404、注册时机过早,这三个问题占了实际报错的 90% 以上。
浏览器只允许在安全上下文(secure context)中注册 Service Worker。navigator.serviceWorker.register() 在非 HTTPS 的生产域名(比如 http://example.com)下会直接抛出 SecurityError,连 catch 都捕不到,控制台只显示 “Registration failed: SecurityError”。
http://localhost 和 http://127.0.0.1 被豁免,其他 http 地址(如 http://test.local)一律不工作navigator.serviceWorker.register() 必须在 load 后执行注册调用不能放在 <script> 标签里就立刻执行,否则可能因 DOM 尚未就绪或 navigator 对象未完全初始化而静默失败。常见错误是把注册逻辑写在 DOMContentLoaded 之前,或塞进某个异步模块加载回调里却没等页面真正 ready。
window.addEventListener('load', ...),确保 HTML、CSS、JS 全部加载完成document.addEventListener('DOMContentLoaded', ...) —— 此时 Service Worker 可能还没准备好接管 fetch/sw.js 是否被正确输出到静态目录根路径;访问 https://yoursite.com/sw.js 应返回 JS 文件内容,状态码 200,而非 404看起来 navigator.serviceWorker.register('/sw.js') 返回了 Promise resolve,控制台也打印 “registered”,但后续 fetch 事件根本不触发——大概率是 scope 范围没覆盖到你要拦截的页面。
立即学习“前端免费学习笔记(深入)”;
sw.js 所在路径的父目录,比如 /assets/sw.js 的默认 scope 是 /assets/,它无法拦截根目录下的 /index.html
{ scope: '/' } 可强制扩大作用域,但前提是 sw.js 文件本身也得在可访问的上级路径(例如放在根目录)/sw.js 的 scope 设为 /admin/,也不能把 /scripts/sw.js 的 scope 设为 /(浏览器会拒绝)注册成功只是第一步,真正缓存资源靠的是 install 事件。如果控制台没打印 “Installing” 或缓存没生效,问题往往出在 sw.js 文件本身。
Content-Type: text/javascript,某些 Nginx/Apache 配置会把无扩展名文件(或 .js 文件)误判为 text/plain,导致 install 不触发sw.js 里不能有语法错误(哪怕一个逗号错位),整个脚本会加载失败,且错误通常只出现在 DevTools → Console 的 “Service Worker” 分组下,容易被忽略self.skipWaiting() 在 install 里可跳过等待(配合 clients.claim() 在 activate 中使用)sw.js 开头加 console.log('SW loaded'),然后在 DevTools → Application → Service Workers → “Update on reload” 打钩,刷新页面看日志是否出现最常被忽略的一点:Service Worker 的生命周期是异步且延迟生效的。注册后刷新一次页面,install 才开始;再刷新一次,activate 才完成并真正接管 fetch。断网测试前,务必手动刷新两次,别信“注册完就能离线”。