首先需要明确:Service Worker 受浏览器同源策略(Same-Origin Policy)的严格限制,它只能在与其脚本本身同源(协议、主机名、端口均相同)的客户端页面中注册、控制作用域。因此,从规范层面讲,Service Worker 无法原生实现真正的“跨域名”注册或控制。一个域名 A 上的 Service Worker 不可能直接控制域名 B 上的页面,即使域名 A 和域名 B 是主/子域名关系。

如果您的需求是“让多个域名共享同一套 Service Worker 逻辑”,常见的专业解决方案是将 Service Worker 代码发布为公共静态资源,并在每个域名下分别注册。具体做法是:在各域名的自身源(如 https://a.example.com/sw.js)部署相同或相似的 Service Worker 脚本(或通过 importScripts() 从跨域 CDN 加载公共模块)。注意:importScripts() 可以加载跨域脚本,但脚本必须支持 CORS 或正确的跨域头,同时主 Service Worker 脚本本身必须与注册页面同源。
如果需求是“让 Service Worker 拦截并处理跨域请求(Cross-Origin Requests)”,这是允许的。您可以在 Service Worker 的 fetch 事件中调用 fetch() 获取跨域资源(例如图片、接口数据),并通过 CORS 或 no-cors 模式进行响应。但必须注意:开发环境下跨域请求需要目标服务器返回正确的 Access-Control-Allow-Origin 头,否则请求会被浏览器拦截;Service Worker 自身并不能绕过 CORS 限制,只是提供了在请求发送前进行缓存、改写、代理的能力。
如果需求是“不同域名页面之间通过 Service Worker 通信”,这同样不可直接实现。Service Worker 只能与其作用域内的客户端(同源窗口)通过 postMessage() 通信。对于跨域页面,可以采取通过主窗口与 iframe 桥接或利用 BroadcastChannel API 等间接手段,但这些方式不属于 Service Worker 跨域,而是页面级跨域通信。
另一个容易混淆的技术是 Service-Worker-Allowed 响应头。该响应头可以扩大 Service Worker 的路径作用域(scope),例如从 sw.js 所在目录向上扩展到根目录,但无法超过源(origin)的限制。也就是说,它只能控制同一协议、同一主机、同一端口下的路径范围,不能跨越到不同主机或端口。
此外,document.domain 修改不会影响 Service Worker 的同源判断。虽然旧式页面间可以通过设置 document.domain 实现子域互操作,但 Service Worker 的源是基于 URL 的绝对匹配,因此即使两个子域共享主域标签,也不能通过 document.domain 让 Service Worker 跨域注册或控制。
对于真实的业务部署(如多个子站点共用登录态、缓存策略),推荐的架构是为每个子域名单独注册 Service Worker,并通过 共享代码模块或构建时拉入公共脚本来保持逻辑一致。同时,可以利用 Service Worker 的缓存策略来统一管理跨域 CDN 资源,比如在 fetch 事件中判断请求 URL,若是 CDN 资源则进行缓存优先处理,从而实现跨域名资源的统一加速。
总结:Service Worker 无法直接跨域名,这是浏览器安全模型决定的核心约束。跨域场景下,应围绕“同源注册 + 跨域资源共享”进行设计:在各目标域独立注册 SW,通过 importScripts 复用代码;利用 fetch 代理跨域网络请求;结合 CORS 或 CDN 实现跨域缓存与资源分发。切勿试图突破同源策略,因为这会破坏 Web 安全基石。

查看详情

查看详情