Service Worker 的 scope 必须是脚本 URL 的前缀或同级目录,脚本必须物理位于 scope 目录内或其子目录中;/js/sw.js 不可设 scope: '/',否则浏览器报错拒绝注册。

Service Worker 的作用域(scope)不能随意设为比脚本位置更“高”的路径,这是浏览器强制执行的安全限制。比如把 /js/sw.js 注册时设 scope: '/',会直接报错:The path of the provided scope ('/') is not under the max scope allowed ('/js/')。这不是配置疏漏,而是规范本身不允许脚本“越权”控制自己所在目录之上的资源。
明确 scope 与脚本路径的包含关系
scope 必须是 Service Worker 脚本 URL 的「前缀」或同级目录。换句话说,脚本必须物理上位于 scope 所指目录内或其子目录中。
- ✅ 正确:脚本在
/sw.js,注册时用{ scope: '/' } - ✅ 正确:脚本在
/assets/sw.js,注册时用{ scope: '/assets/' }或{ scope: '/' }(需服务端配合) - ❌ 错误:脚本在
/js/sw.js,却设{ scope: '/' }—— 浏览器拒绝 - ❌ 错误:脚本在
/admin/sw.js,却设{ scope: '/user/' }—— 路径无包含关系
绕过限制的三种可行方式
当确实需要让一个 SW 控制整个站点(包括根路径下的 HTML 和静态资源),但脚本又不能直接放在根目录时,可选以下任一方案:
-
移动脚本到根目录:把
sw.js放到网站根路径(如https://example.com/sw.js),再用navigator.serviceWorker.register('/sw.js', { scope: '/' })注册 -
用 Service-Worker-Allowed 响应头:保持脚本在
/js/sw.js,但在服务器返回该文件时添加 HTTP 响应头Service-Worker-Allowed: /,告诉浏览器“允许它控制根路径” -
调整部署结构:若使用子路径部署(如
https://example.com/myapp/),把 SW 放在/myapp/sw.js,注册时显式传{ scope: '/myapp/' },确保 scope 与实际访问路径一致
验证 scope 是否生效
注册成功后,可通过 registration.scope 检查最终生效的 scope 值。更重要的是观察实际行为:
- 打开
chrome://serviceworker-internals/,查看对应站点的 SW 列表,确认 scope 字段是否符合预期 - 在 Application → Service Workers 面板中,点击 “Update on reload”,刷新页面,看 fetch 事件是否触发(尤其测试根路径下
/index.html、/css/main.css等请求) - 若某些资源未被拦截,检查它们的请求 URL 是否真在 scope 范围内(注意尾部斜杠、大小写、编码等细节)
避免 scope 冲突的常见操作
多个 SW 共存时,scope 必须互不重叠(同源下允许注册多个,但 scope 不能相同或嵌套):
- 不要在同一 scope 下重复注册不同版本的 SW,否则新版可能无法激活
- 开发调试阶段,如果换了项目但没清缓存,旧 SW 可能仍在控制页面——手动在
chrome://serviceworker-internals/中 unregister,再硬性刷新 - 上线新版本前,确保 manifest.json 中的
scope与 SW 注册时的 scope 一致,否则 PWA 安装可能失败或 start_url 解析异常











