Service Worker 可以拦截页面的所有接口请求吗?

Service Worker 可以拦截页面的绝大多数网络请求,但并非所有请求都能被拦截,具体取决于请求的类型、来源以及浏览器的缓存机制。以下是详细分析:

1. 可拦截的请求类型

Service Worker 可以拦截以下类型的请求:

  • HTTP/HTTPS 请求:包括 fetchXMLHttpRequest 等发起的网络请求。
  • 静态资源请求:如 HTML、CSS、JavaScript、图片、字体等文件的请求。
  • API 请求:包括 RESTful API、GraphQL 等动态接口请求。
  • 跨域请求:Service Worker 可以拦截跨域请求,但需要确保 CORS 配置正确。
  • WebSocket 连接请求:Service Worker 可以拦截 WebSocket 的初始握手请求。
  • Push 通知请求:Service Worker 可以处理来自服务器的推送通知请求。

2. 不可拦截的请求

以下情况下的请求可能无法被 Service Worker 拦截:

  • 内存缓存(Memory Cache)中的资源:浏览器会优先从内存缓存加载资源,此时 Service Worker 无法介入。
  • Service Worker 自身脚本的请求:Service Worker 无法拦截自身的更新请求。
  • 非同源请求(未正确配置 CORS):默认情况下,Service Worker 只能拦截同源请求,跨域请求需额外处理。
  • 浏览器内部请求:如 chrome://about: 等特殊协议的请求不受 Service Worker 控制。

3. 拦截的限制

  • HTTPS 或 localhost 环境:Service Worker 必须在 HTTPS 或本地开发环境(localhost)下运行。
  • 作用域限制:Service Worker 只能拦截其注册作用域(scope)下的请求。
  • 首次加载不受控制:用户首次访问页面时,Service Worker 尚未激活,无法拦截初始请求。

4. 实际应用示例

// service-worker.js
self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request)
        .then((response) => {
            if (response) {
                return response; // 返回缓存
            }
            return fetch(event.request); // 否则继续网络请求
        })
    );
});

这段代码展示了 Service Worker 如何拦截 fetch 请求并优先返回缓存内容。

5. 总结

Service Worker 可以拦截页面的绝大多数网络请求,但受限于浏览器缓存策略、同源策略及 HTTPS 要求。合理利用其缓存和请求拦截能力,可以实现离线访问、请求重试、资源优化等功能。