参考
简易用法, 甚至可以直接复制粘贴使用
在主线程中安装
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js')
}
sw.js
const VERSION = 'v1';
// 缓存
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open(VERSION).then(function (cache) {
return cache.addAll([]);
})
self.skipWaiting()
);
});
// 删除旧版本sw的缓存
self.addEventListener('activate', function (event) {
console.log('service worker activate');
event.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (cacheName) {
// 如果当前版本和缓存版本不一致
if (cacheName !== VERSION) {
return caches.delete(cacheName);
}
})
);
})
);
});
// 捕获请求并返回缓存数据
self.addEventListener(
'fetch',
/**
* @param {{request: Request}} event
*/
function (event) {
event.respondWith(
caches.match(event.request).then(function (response) {
if (response) {
return response;
}
const request = event.request.clone();
return fetch(request)
.then((res) => {
if (!res || res.status !== 200) {
return res;
}
const responseToCache = res.clone();
caches.open(VERSION).then(function (cache) {
cache.put(requst, responseToCache);
});
return res;
})
.catch(() => {
return fetch(event.request.url, { mode: 'no-cors' });
});
})
);
}
);
一些踩坑记录
- sw中的
event.respondWith不存在后悔项, 我的意思是, 一旦调用了这个接口, 就要想办法返回一个内容. 不能在发现出错后继续走原有的请求 - request在捕获时还没有拿到cookies, 而sw本身是没有cookies缓存的, 也就是说如果服务端校验了cookies的话, 会导致本来正常请求可以获得结果的, 但使用了sw捕获之后反而出错了.
- 默认的img请求, 它的request设置默认是'no-cors'的, 这个参数的意义是即便我们捕获了返回, 也会发现res.data是null, 将这个res缓存下来下次返回, 所以必须要手动新建一个request并且设置为'cors', 但这时候也有可能出错, 本人当前的方法是直接
fetch(event.request.url)并缓存. 所以在这里, 有的时候使用request.clone才能得到正确返回, 有的时候必须使用url才能得到正确返回, 这里面的区别就需要仔细区分测试才行.
跨域的缓存
- sw其实也支持跨域, 只需要服务端返回
Access-Control-Allow-Origin: *, 就可以得到跨域的缓存.