Service Worker是实现静态资源离线访问的核心机制,需在HTTPS或localhost下注册,通过install预缓存、fetch拦截响应、activate清理旧缓存,并用skipWaiting和clients.claim实现立即生效。

Service Worker 是浏览器提供的后台脚本,能拦截网络请求、控制缓存策略,是实现静态资源离线访问的核心机制。关键在于注册 Service Worker、监听 install 和 fetch 事件,并用 Cache API 主动管理缓存。
注册 Service Worker
必须在 HTTPS 环境(或 localhost)下运行。注册代码需放在主页面的 JavaScript 中,且通常只执行一次:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered:', reg.scope))
.catch(err => console.error('SW registration failed:', err));
});
}
-
路径注意:注册路径
/sw.js决定了 Service Worker 的作用域(scope),建议放在根目录以覆盖整个站点 -
刷新时机:新版本 SW 在页面第二次打开时才激活,可用
skipWaiting()+clients.claim()实现立即生效(开发阶段可加)
安装阶段预缓存静态资源
在 install 事件中,打开缓存并添加指定文件(如 HTML、CSS、JS、字体、图片等):
const CACHE_NAME = 'static-v1';
const PRECACHE_URLS = [
'/',
'/index.html',
'/styles/main.css',
'/scripts/app.js',
'/images/logo.png'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(PRECACHE_URLS))
.then(() => self.skipWaiting())
);
});
-
缓存命名规范:版本号(如
static-v1)便于更新后清除旧缓存 - addAll 风险:任一资源失败将导致整个 install 失败,生产环境建议逐个 fetch + put,增强健壮性
拦截请求并响应缓存
在 fetch 事件中判断请求是否命中预缓存,优先返回缓存内容,未命中再发起网络请求并存入缓存(可选):
立即学习“Java免费学习笔记(深入)”;
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// 只处理同源 GET 请求(跳过 favicon、跨域等)
if (event.request.method !== 'GET' || url.origin !== location.origin) {
return;
}
event.respondWith(
caches.match(event.request)
.then(cached => cached || fetch(event.request))
.then(response => {
// 可选:对非 HTML 资源做运行时缓存(如 API 响应)
if (response && response.type === 'basic' && !url.pathname.endsWith('.html')) {
const copy = response.clone();
caches.open(CACHE_NAME).then(cache => cache.put(event.request, copy));
}
return response;
})
);
});
-
match 逻辑:默认精确匹配 URL,带查询参数的请求需注意(如
/api/data?ts=123不会命中/api/data) - HTML 特殊处理:通常不缓存 HTML(避免页面陈旧),而是用 Network-First 或 Stale-While-Revalidate 策略
缓存清理与版本升级
每次更新 SW 文件内容(哪怕只改一个空格),浏览器都会视为新版本。旧缓存不会自动删除,需手动清理:
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keys => {
return Promise.all(
keys.map(key => {
if (key !== CACHE_NAME) {
return caches.delete(key);
}
})
);
}).then(() => self.clients.claim())
);
});
-
激活前清理:在
activate阶段删除历史缓存,防止磁盘占用持续增长 - claim() 作用:让新 SW 立即接管当前页面(否则需刷新两次)


















