一.作用
1.离线缓存。Server worker安装启动后对当前配置的文件进行缓存,界面刷新或者重进进入界面时只要server Worker未被注销则可从缓冲中读取命中的目标文件,以达到类applacationCache
2.消息推送。推送消息到被server worker接收管理的界面。
3.后台数据同步,后台下载更新文件不影响当前界面
4.请求劫持。
5.地理围栏,时间日期的响应,相同域名之间的切换,处理运算成本比较高的数据,预取资源比如下一组列表数据等等。
二.概念
Service Worker 首先是一个运行在后台的 Worker 线程,然后它会长期运行,充当一个服务,很适合那些不需要网页或用户互动的功能。它的最常见用途就是拦截和处理网络请求。为了节省内存,Service worker 在不使用的时候是休眠的。它也不会保存数据,所以重新启动的时候,为了拿到数据,最好把数据放在 IndexedDb 里面。
,Service Worker不可用。特点总结如下:
- · ServiceWorker工作在worker context中,是没有访问DOM的权限的,所以我们无法在Service Worker中获取DOM节点,也无法在其中操作DOM元素;
- ·我们可以通过postMessage接口把数据传递给其他JS文件;
- · Service Worker中运行的代码不会被阻塞,也不会阻塞其他页面的JS文件中的代码;
三.注册
-
注册
navigator.serviceWorker.register('sw.js'.then(() => { console.info('注册成功') }).catch((err) => { console.error('注册失败') })
新建如上代码在index.html引入。
- scope
- sw.js
2.监测生命周期
- 安装:
self.addEventListener('install', event => {
event.waitUntil(() => console.info('安装完成'))
})
event.waitUntil() 方法为事件完成后指定回调函数。
- 激活
3.更新
四.通信
通信 页面发送消息到ServiceWorker
// app.js
navigator.serviceWorker.controller
&& navigator.serviceWorker.controller.postMessage("this message is from page");
在sw.js文件中可以使用如下方式接收:
// sw.js
self.addEventListener('message', function (event) {
console.log(event.data); // this message is from page
});
通信 ServiceWorker发送消息到页面
-
从serviceWorker到页面的信息传递最简单的方式是通过监听页面发送到serverWorker的消息然后获取windowClients,然后在windowClients上调用window的postMessage发送消息到页面,但是局限性也很大,必须要接收到页面发送到serviceWorker的消息后才能发送消息。例:
// sw.js 接收到消息后再发送信息 this.addEventListener('message', function (event) { event.source.postMessage('this message is from sw.js, to page'); });
// app.js 通过监听message消息接收信息 navigator.serviceWorker.addEventListener('message', function (e) { console.log(e.data); // this message is from sw.js, to page });
// sw.js
this.clients.matchAll().then(client => {
client[0].postMessage('this message is from sw.js, to page');
})
五.资源缓存
缓存指定资源
// sw.js 缓存指定静态资源
this.addEventListener('install', function (event) {
console.log('install');
event.waitUntil(caches.open('sw_demo').then(function (cache) {
return cache.addAll(['/style.css','/panda.jpg','./main.js'])
}));
});
CacheStroage在浏览器中的接口名称是caches,我们可以通过caches.open方法新建或者打开一个已存在的缓存。Cache.addAll方法的作用是请求指定链接页面的资源把他们储存到之前打开的缓存中(具体操作详解请查看CacheStroage API)。由于IO操作是异步操作锦衣将方法放置于event.waitUntil方法,其能保证资源被缓存完成前sw本身不被重新安装或者其余操作导致终止或者退出。缓存完成后可以在Chrome开发工具中的Application的Cache Strogae中可以看到我们缓存的资源。
缓存所有网络资源
this.addEventListener('fetch', function (event) {
console.log(event.request.url);
event.respondWith(caches.match(event.request).then(res => {
return res || fetch(event.request).then(responese => {
const responeseClone = responese.clone();
caches.open('sw_demo').then(cache => {
cache.put(event.request, responeseClone);
})
return responese;
}).catch(err => {
console.log(err);
});
}))
});
- 当用户第一次访问页面的时候,资源的请求是早于Service Worker的安装的,所以静态资源是无法缓存的;只有当Service Worker安装完毕,用户第二次访问页面的时候,这些资源才会被缓存起来;
- Cache Stroage只能缓存静态资源,所以它只能缓存用户的GET请求;
- Cache Stroage中的缓存不会过期,但是浏览器对它的大小是有限制的,所以需要我们定期进行清理;
- 更新缓存CacheStroage
// sw.js 更换缓存命名空间
this.addEventListener('install', function (event) {
console.log('install');
event.waitUntil(caches.open('sw_demo_v2').then(function (cache) {
// 更换缓存命名空间
return cache.addAll(['/style.css','/panda.jpg','./main.js'])
}))
});
const cacheNames = ['sw_demo_v2'];
// sw.js 校验过期的缓存进行清除
this.addEventListener('activate', function (event) {
event.waitUntil(caches.keys().then(keys => {
return Promise.all[keys.map(key => {
if (!cacheNames.includes(key)) {
console.log(key);
return caches.delete(key); // 删除不在白名单中的 Cache Stroage
}
})]
}))
});