Service Worker 拦截网络请求需注册脚本、监听 fetch 事件并满足 HTTPS 等前提;作用域决定拦截范围,fetch 中依 destination/mode 匹配缓存或转发,POST 请求需谨慎处理请求体。

网页应用使用 Service Worker 拦截并处理网络请求,核心在于注册一个有效的 Service Worker 脚本,并在其中监听 fetch 事件,对请求进行判断、响应或转发。整个过程需满足 HTTPS(或 localhost)、作用域匹配、正确缓存策略等前提,否则拦截不会生效。
注册 Service Worker 并确认作用域
Service Worker 必须通过 JavaScript 在页面中显式注册,且其作用域(scope)决定了它能拦截哪些请求:
- 注册代码应放在
window.addEventListener('load', ...)中,确保 DOM 和资源加载完成后再执行 - 若希望拦截根路径下所有请求(如
/index.html、/api/data),推荐将 SW 文件(如sw.js)放在网站根目录,并显式指定{ scope: '/' } - 错误示例:把
sw.js放在/js/sw.js却不设scope,则它默认只能拦截/js/及其子路径,无法捕获/css/app.css
在 fetch 事件中实现请求拦截
fetch 是 Service Worker 最关键的监听事件,所有受控页面发起的网络请求都会触发它。你可以在回调中决定是返回缓存、伪造响应,还是放行到网络:
设置基于 systemd 的看门狗,使 Node.js 长运行服务(如 Telegram 机器人、Express 仪表盘等)在 shell 退出、SSH 断开等情况下保持运行。
- 用
event.request.url或new URL(event.request.url)提取协议、域名、路径等信息,做精准匹配 - 对静态资源(CSS/JS/图片)可优先查缓存:
caches.match(event.request),命中则直接返回 - 对广告或分析脚本等第三方请求,可匹配域名后返回空响应:
new Response('', { status: 200 }) - 对 API 请求,通常不缓存响应体,而是直接
fetch(event.request)并按需处理返回值
注意请求模式与缓存匹配细节
不是所有请求都能被缓存或成功匹配,需关注 Request.destination 和 Request.mode 等属性:
-
request.destination === 'document'表示主页面 HTML 请求,适合 stale-while-revalidate 策略 -
request.destination === 'script'或'style'应强缓存,避免白屏或样式错乱 -
request.mode === 'cors'多为跨域 API,缓存时需确保credentials选项一致,否则cache.match()会失败 - 带查询参数的 URL(如
logo.png?v=123)必须原样缓存,否则无法匹配
处理 POST/上传类请求的特殊限制
Service Worker 可以拦截 POST 请求,但不能像 GET 那样简单缓存响应——尤其对文件上传等操作:
- XMLHttpRequest 的 POST 请求体是单向消耗的,一旦在
fetch中读取(如request.arrayBuffer()),原始请求就失效,后续fetch(request)会报错 -
cache.put()对上传响应基本无效,因其响应往往无重放价值(如 204 No Content) - 可行做法:前端改用
fetch()发起上传,提前将 body 转为ArrayBuffer,再构造新Request,便于多次使用 - 真正需要离线提交的场景,建议结合
background syncAPI,在网络恢复后自动重发

















