Service Worker 本身不支持动态灰度发布,需协同fetch事件路由逻辑、外部可变信号(如Cookie/请求头)和构建时带版本的资源路径三者实现;灰度标识须在fetch事件中读取并构造含版本信息的缓存键,注册sw.js时需动态注入版本参数以规避强缓存。

Service Worker 本身不能“动态灰度发布”,它只是个被动注册的脚本;真正起作用的是你在 fetch 事件里写的路由逻辑 + 外部可变信号(如 Cookie、请求头)+ 构建时带版本的资源路径。不配合这三者,光改 SW 代码毫无意义。
fetch 事件中如何读取灰度标识并构造版本化缓存键
灰度开关(比如 gray=beta)不能在 install 阶段读取,因为此时文档上下文不可用;只能在 fetch 事件中通过 document.cookie 或 request.headers.get('x-gray-flag') 获取。但注意:document.cookie 在 SW 环境中需从主页面同步注入(例如初始化时写入 localStorage 或通过 postMessage),否则会读不到。
- 推荐方式:服务端在 HTML 响应头中设置
x-gray-flag: canary,SW 中用event.request.headers.get('x-gray-flag')读取 - 缓存键必须包含版本信息,例如
https://cdn.example.com/app.js?v=2.1.0&gray=canary,而非裸 URL - 避免用
location.hostname等运行时变量拼接 key——SW 中无location对象,要用new URL(event.request.url) - 若用 Cookie,务必确保
SameSite=Lax或Strict不阻断,且 SW 注册域与主站同源
如何让不同灰度用户加载不同版本的 sw.js
浏览器对同一 scope 的 sw.js 有强缓存,navigator.serviceWorker.register('sw.js') 只会触发一次 fetch。所以不能靠“改内容”让已注册 SW 自动更新,而要让注册地址本身带版本或分流参数。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- HTML 中动态写入注册路径:
navigator.serviceWorker.register('/sw.js?v=' + version),其中version由后端根据灰度策略注入 - CDN 层按请求头或 Cookie 返回不同 HTML 入口文件,每个入口含对应版本的
register()调用 - 绝对不要用
self.skipWaiting()强制激活新 SW——它会让所有用户立即切版本,破坏灰度隔离 - 旧版 SW 的
activate事件里,用caches.delete()清理过期缓存名(如cache-v1.2.0),但别删错名字,建议命名规则为static-${version}-${gray}
静态资源代理路由怎么匹配和重写 URL
不是所有请求都要代理,得按路径、方法、甚至 query 参数做细粒度控制。比如只把 /assets/ 下的 JS/CSS 重定向到带版本的 CDN 地址,而图片走默认路径。
- 用
new URL(event.request.url)解析原始请求,检查pathname.startsWith('/assets/') - 构造目标 URL 时,保留原始 hash 和 search,仅替换 origin 和 pathname 前缀:
url.origin = 'https://cdn-beta.example.com'; url.pathname = url.pathname.replace(/^\/assets/, '/v2.1.0/assets'); - 对 POST 请求慎用代理——静态资源一般不用 POST,若误配会导致表单提交失败
- 若需 fallback 到网络,用
event.respondWith(fetch(newRequest).catch(() => caches.match(cacheKey))),避免因 CDN 故障导致白屏
最易被忽略的一点:灰度标识必须在请求发出前就确定,不能依赖 fetch 后响应体内容。也就是说,所有决策逻辑(包括版本选择、缓存读写、URL 重写)都得在 fetch 事件开头完成,中间不能有异步等待——SW 的 fetch 事件监听器必须同步返回 event.respondWith()。


















