serviceWorker 离线缓存功大大提高了用户体验,因为它可以对页面的资源选择性的从缓存读取从而提高页面加载效率
下面简单实现一个无网络环境中加载项目页面功能:
src/main.ts
// 判断浏览器是否支持 serviceWorker功能,一般正式环境需要https 开发环境需要http://localhost
if ("serviceWorker" in navigator) {
// 加载serviceWorker 脚本,service-worker.js 一般情况写在 public 文件夹中
navigator.serviceWorker.register("/service-worker.js").then((res)=>{
console.log(res,'成功')
}).catch(()=>{
console.log('失败')
})
}
在main.ts中加入,执行加载serviceWorker.js脚本
在public文件夹中创建 service-worker.js
public/service-worker.js
// service-worker 脚本初次加载时执行
self.addEventListener('install', () => {
// 安装后立即激活
self.skipWaiting()
})
// 拦截所有请求
self.addEventListener('fetch', (event) => {
// event.respondWith() 允许我们自定义如何响应 fetch 事件
// 这意味着我们可以决定是直接使用缓存的响应、发起网络请求,还是执行其他操作
event.respondWith(
// 首先尝试从缓存中获取请求的响应
caches.match(event.request)
.then(function (cachedResponse) {
// 如果缓存中存在匹配的响应
if (cachedResponse) {
// 直接返回缓存中的响应
// 这样可以提高性能,因为不需要从网络获取资源
return cachedResponse;
}
// 如果缓存中没有匹配的响应,则向网络发起请求
return fetch(event.request)
.then(function (response) {
// 当从网络获取到响应后
// 打开名为 'my-cache' 的缓存
return caches.open('my-cache')
.then(function (cache) {
// 将从网络获取到的响应克隆一份存储到缓存中
// 为什么要克隆?因为 response 对象只能被消费一次
// 我们需要保留一份用于返回给页面,另一份用于存储到缓存中
// 如果不是Chrome 扩展则进行缓存
if (!event.request.url.startsWith('chrome-extension://')) cache.put(event.request, response.clone());
// 返回原始的网络响应给页面
return response;
});
});
})
);
})
// service-worker 首次安装或更新后触发
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (cacheName) {
if (expectedCacheNames.indexOf(cacheName) == -1) {
// 清理旧缓存
return caches.delete(cacheName);
}
})
);
}),
);
})
验证效果如下:把网络断开,但是页面还是正常展示。是因为在service-worker.js中把加载过的网络资源进行缓存。之后进入页面直接读取缓存内容从而做到“离线加载”
ps:如果效果未实现可以排查一下
serviceWorker 是否加载正常,脚本来源是正确。
注:以上功能仅仅只是最基本的serviceWorker离线缓存功能的实现,正常开发中业务往往比上面的案例会复杂很多。所以需要结合实际项目情况进行定制化修改,或者使用开源serviceWorker 的依赖。。。