特点:
.本质上充当服务器与浏览器之间的代理服务器(可以拦截全站的请求,并作出相应的动作->由开发者指定的动作)
.在web worker的基础上增加了离线缓存的能力
.由事件驱动的,具有生命周期,其生命周期与页面无关(关联页面未关闭时,它也可以退出,没有关联页面,它也可以启动)
.可以访问cache和indexDB
.完全异步,同步API(如XHR和localStorage)不能在service work中使用
.只能为https承载
.可以被多个页面所共享(同域情况下)
.不能缓存POST请求
应用场景:
.跟 Fetch 搭配,可以从浏览器层面拦截请求,做数据 mock;
.跟 Fetch 和 CacheStorage 搭配,可以做离线应用;
.跟 Push 和 Notification 搭配,可以做像 Native APP 那样的消息推送
激活流程:
.在navigator.serviceWorker.register进行注册后
.用户首次访问service worker控制的网站或页面时,service worker会立刻被下载
.无论它与现有service worker不同(字节对比),还是第一次在页面或网站遇到service worker,如果下载的文件是新的,安装就会尝试进行
.安装成功后它会被激活
.如果现有service worker已启用,新版本会在后台安装,但不会被激活,这个时序称为worker in waiting
.直到所有已加载的页面不再使用旧的service worker才会激活新的service worker。只要页面不再依赖旧的service worker,新的service worker会被激活(成为active worker)。
跳过等待:this.skipWaiting();
跳过installing,直接接管老的service worker,触发activate,在self.addEventListener('install')中调用
手动更新客户端:self.clients.claim(),
在self.addEventListener('activate')中清除完旧缓存后调用
.之后,在以下情况将会触发更新:
.一个前往作用域内页面的导航
.在 service worker 上的一个事件被触发并且过去 24 小时没有被下载
基本使用:
Service Worker 注册的代码是放在 HTML 的最后,如果页面加载时没有Service Worker,那么它所依赖的其他资源请求也不会触发 fetch 事件。
1、注册service worker
.如果注册成功,service worker就会被下载到客户端并尝试安装或激活,这将作用于整个域内用户可访问的URL,或者其特定子集
navigator.serviceWorker.register(url,options)
url:service worker文件的路径,路径是相对于 Origin ,而不是当前文件的目录的
optionts
scope:表示定义service worker注册范围的URL ;service worker可以控制的URL范围。通常是相对URL。默认值是基于当前的location(./),并以此来解析传入的路径.
假设你的sw文件放在根目录下位于/sw/sw.js路径的话,那么你的sw就只能监听/sw/*下面的请求,如果想要监听所有请求有两个办法,一个是将sw.js放在根目录下,或者是在注册是时候设置scope。
如设置为/app/即app地址路径下的所有页面如/app/index.html;/app/main/index.html。`
避免第一次打开页面就进行缓存,占用主线程的带宽,以及加剧对cpu和内存的使用
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js');
});
}
if ('serviceWorker' in window.navigator) {
navigator.serviceWorker.register('./sw.js', { scope: './' })
.then(function (res) {
res:ServiceWorkerRegistration实例
})
.catch(function (err) {
console.log('fail', err);
});
注册多个service worker,但scope必须是不同的
navigator.serviceWorker.register('./sw/sw.js', { scope: './sw' })
.then(function (reg) {
console.log('success', reg);
})
navigator.serviceWorker.register('./sw2/sw2.js', { scope: './sw2' })
.then(function (reg) {
console.log('success', reg);
})
}
1.5、方法
主线程中:
(1)发送信息
if ('serviceWorker' in window.navigator) {
navigator.serviceWorker.register('./sw.js', { scope: './' })
.then(function (reg) {
方式一:
.如果使用的scope不是Origin下使用
.reg.active就是被注册后激活 Serivce Worker 实例
.由于Service Worker的激活是异步的,因此第一次注册 Service Worker 的时候,Service Worker 不会被立刻激活, reg.active 为 null
reg.active.postMessage("this message is from page, to sw");
方式二:
确定当前serviceWorker已经激活安装完成
navigator.serviceWorker.controller && navigator.serviceWorker.controller.postMessage("this message is from page");
方式三:通过messageChannel
});
方式四:
navigator.serviceWorker.register('service-worker.js');
navigator.serviceWorker.ready.then( registration => {
registration.active.postMessage("Hi service worker");
});
(2)销毁service worker
if ('serviceWorker' in navigator) {
//获取所有注册的service worker
navigator.serviceWorker.getRegistrations()
.then(function(registrations) {
for(let registration of registrations) {
//安装在网页的service worker不止一个,找到我们的那个并删除
if(registration && registration.scope === 'https://seed.futunn.com/'){
registration.unregister(); //进行销毁
}
}
});
}
(3)更新service worker
var version = '1.0.1'
navigator.serviceWorker.register('/sw.js')
.then((reg) => {
if(localStorage.getItem('sw_version') !== version) {
reg.update()
.then(() => {
localStorage.setItem('sw_version', version)
})
}
})
在service worker脚本文件中:
(1)发送消息
this.addEventListener('message', function (event) {
必须使用event.source进行发送,在其他能获取到的函数中也可以
event.source.postMessage('this message is from sw.js, to page');
});
方式二:
.通过窗口发送,即注册了该serviceWoker的页面的clients对象(即windows对象)
.client必须要接收到页面发送到serviceWorker的消息后才能发送消息
this.clients.matchAll().then(client => {
client[0].postMessage('this message is from sw.js, to page');
})
方式三:
通过messageChannel
2、监听
在service worker脚本文件中
(1)监听被下载安装
this.addEventListener('install', function (event) {
console.log('Service Worker install');
});
var CACHE_VERSION = 1;
var CURRENT_CACHES = {
prefetch: 'prefetch-cache-v' + CACHE_VERSION
};
self.addEventListener('install', function(event) {
var urlsToPrefetch = [
'./static/pre_fetched.txt',
'./static/pre_fetched.html',
'https://www.chromium.org/_/rsrc/1302286216006/config/customLogo.gif'
];
event.waitUntil(
caches.open(CURRENT_CACHES['prefetch']).then(function(cache) {
cache.addAll(urlsToPrefetch.map(function(urlToPrefetch) {
return new Request(urlToPrefetch, {mode: 'no-cors'});
})).then(function() {
console.log('All resources have been fetched and cached.');
});
}).catch(function(error) {
console.error('Pre-fetching failed:', error);
})
);
});
(2)监听被激活
.触发时可以清理旧缓存和旧的service worker关联的东西
this.addEventListener('activate', function (event) {
console.log('Service Worker activate');
});
(3)监听信息发送
this.addEventListener('message', function (event) {
console.log(event.data);
});
(4)监听浏览器请求
this.addEventListener('fetch', function (event) {
...
}
主线程监听
(1)监听消息发送
navigator.serviceWorker.addEventListener('message', function (e) {
console.log(e.data);
});
(2)监听service worker是否改变
navigator.serviceWorker.addEventListener('controllerchange', () => {
window.location.reload();
})
3、记录service worker的生命周期
if ('serviceWorker' in navigator) {
$('#isSupport').text('支持');
// 开始注册service workers
navigator.serviceWorker.register('./sw-demo-cache.js', {
scope: './'
}).then(function (registration) {
$('#isSuccess').text('注册成功');
var serviceWorker;
if (registration.installing) {
serviceWorker = registration.installing;
$('#state').text('installing');
} else if (registration.waiting) {
serviceWorker = registration.waiting;
$('#state').text('waiting');
} else if (registration.active) {
serviceWorker = registration.active;
$('#state').text('active');
}
if (serviceWorker) {
$('#swState').text(serviceWorker.state);
serviceWorker.addEventListener('statechange', function (e) {
$('#swState').append(' 状态变化为' + e.target.state);
});
}
}).catch (function (error) {
$('#isSuccess').text('注册没有成功');
});
} else {
$('#isSupport').text('不支持');
}
</script>
4、离线背景同步
.可以先将网络相关任务延迟到用户有网络的时候再执行
.可以用于保证任何用户在离线的时候所产生对于网络有依赖的操作,最终可以在网络再次可用的时候抵达它们的目标。
.离线期间所有相同事件只会触发一次,如果希望每一次点击都能触发 sync 事件,就需要在注册的时候赋予它们不同的tag。
navigator.serviceWorker.ready
.then(registration => {
document.getElementById('submit').addEventListener('click', () => {
背景同步操作
registration.sync.register('submit').then(() => {
console.log('sync registered!');
});
});
});
service worker中:
self.addEventListener('sync', event => {
if (event.tag === 'submit') {
console.log('sync!');
}
});
5、最佳实践
为了保证离线缓存的资源和真实资源一致,优先使用在线资源(即http请求),sw充当本地和线上服务器的代理服务器角色;当在线资源获取出错(服务器宕机,网络不可用等情况),则使用sw本地缓存
优先从线上获取,获取之后设置缓存,以便下一次获取html出错时候再从本地缓存获取的是上一次获取的文件
请求拦截:
this.addEventListener('fetch', function (event) {
if(event.request.method === 'POST') {
event.respondWith(
new Promise(resolve => {
event.request.json().then(body => {
console.log(body); // 用户请求携带的内容
})
resolve(new Response({ a: 2 })); // 返回的响应
})
)
}
}
}
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
return fetch(event.request).then(function(response) {
return response;
}).catch(function(error) {
throw error;
});
})
);
});
页面缓存:通过Cache Stroage或indexDB进行存储
因为oninstall和onactivate完成前需要一些时间,service worker标准提供一个waitUntil方法,当oninstall或者onactivate触发时被调用,接受一个promise
event.waitUntil
.只能在 Service Worker 的 install 或者 activate 事件中使用;
.如果传递了一个 Promise 给它,那么只有当该 Promise resolved 时,Service Worker 才会完成 install;
.如果 Promise rejected 掉,那么整个 Service Worker 便会被废弃掉。因此,cache.addAll 里面,只要有一个资源获取失败,整个 Service Worker 便会失效。
event.respondWith
.只能在 Service Worker 的 fetch 事件中使用;
.返回一个Promise,当传入的 Promise resolved 之后,才会将对应的 response 返回给浏览器。
.resolve的内容为 Response对象、a network error
(1)静态资源化缓存
this.addEventListener('install', function (event) {
event.waitUntil(
caches.open('sw_demo').then(function (cache) {
return cache.addAll([
'/style.css',
'/panda.jpg',
'./main.js'
])
}
));
});
(2)动态资源缓存
this.addEventListener('fetch', function (event) {
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);
});
})
)
});
代码示例:
资源加载错误,导航错误页
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
}).catch(function() {
return caches.match('/error.html');
})
);
});
错误降级、清除worker
window.addEventListener('load', function() {
const sw = window.navigator.serviceWorker
const killSW = window.killSW || false
if (!sw) {
return
}
if (!!killSW) {
sw.getRegistration('/serviceWorker').then(registration => {
// 手动注销
registration.unregister();
// 清除缓存
window.caches && caches.keys && caches.keys().then(function(keys) {
keys.forEach(function(key) {
caches.delete(key);
});
});
})
} else {
// 表示该 sw 监听的是根域名下的请求
sw.register('/serviceWorker.js',{scope: '/'}).then(registration => {
// 注册成功后会进入回调
console.log('Registered events at scope: ', registration.scope);
}).catch(err => {
console.error(err)
})
}
});
更新、清除缓存
// 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
}
})]
}))
});
雨雀官网的缓存
self.assets = ["https://gw.alipayobjects.com/os/chair-script/skylark/common.b4c03be5.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/common.e2d71ce8.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__components__Explore__Recommend~p__explore__routers__Docs~p__explore__routers__Repos~p_~d6257766.aa1bcc43.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__components__Explore__Recommend~p__explore__routers__Docs~p__explore__routers__Repos~p_~d6257766.fac19d5b.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/c__Lakex~p__editor__routers__TextEditor.9defba11.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/c__Lakex~p__editor__routers__TextEditor.3a98afb8.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__routers.244d87f7.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__routers.ef3c862f.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/c__Lakex.acd5cec4.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/c__Lakex.653d1e93.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/layout__MainLayout.ae548301.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/layout__MainLayout.c0075e36.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__model.511a24e3.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__routers__EditCustomIndex.d4fbfe9e.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__routers__EditCustomIndex.28048163.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__routers__ShareExpired.8113c1a2.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__routers__ShareExpired.b6dff962.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__routers__SharePassword.1a6ae926.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__bookRepo__routers__SharePassword.f76c7685.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__components__Explore__Events.6d43e196.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__components__Explore__Events.979d04c6.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__components__Explore__Recommend.ab8c57cb.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__components__Explore__Recommend.ac025d9d.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__model.2d27d4bc.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__App.4d4a0a8c.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__App.08fcac15.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__CollabBooks.40627926.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__CollabBooks.91d8d56d.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Collects.0a516ca7.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Collects.b5f172fe.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Dashboard.5f89b7f3.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Dashboard.be7c1714.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Explore.b51bb073.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Groups.198f522b.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Groups.ad67b3b7.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__History.086ddd9c.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__History.5387e7a8.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__MyBooks.40627926.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__MyBooks.61608f6e.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Notes.a878e2d7.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Notes.ffe2cc7a.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Recycles.ab448ca1.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__dashboard__routers__Recycles.3434b09c.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__doc__model__page.424fcfd2.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__doc__routers.66f72a35.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__doc__routers.39267068.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__doc__routers__version.e7b71a05.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__doc__routers__version.186ff53b.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__model.7ef254a2.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__Asl.60282b53.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__Asl.fa585dad.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__TextEditor.f413dbfc.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__TextEditor.81c5d11d.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__board.591d841b.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__board.832f1003.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__doc.a1ccd84d.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__doc.e652cf65.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__embed.500645af.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__embed.743631c5.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__embed_extreme.5563bfd4.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__embed_extreme.88434cbe.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__sheet.8a86af45.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__sheet.2daf2fb0.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__show.75463f8e.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__show.14157f9c.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__table.60aad9c2.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__editor__routers__table.29a799ed.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__model.263db0b2.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Books.cfc93cd2.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Books.8ffd07d8.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Custom.710dc957.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Custom.604bf4aa.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Embed.daf129f3.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Embed.1a8cd333.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Error403.8113c1a2.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Error403.e426da8e.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Group.a1fbd1b1.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Group.aca6ba40.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Members.c73713ca.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Members.fc9d4e92.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Migrate.e821f2d6.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Migrate.c5718315.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Recycles.724821a4.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Recycles.9b99a94d.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Statistics.e849f2e3.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Statistics.e2b4dc68.async.js", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Upgrade.a42075c1.chunk.css", "https://gw.alipayobjects.com/os/chair-script/skylark/p__group__routers__Upgrade.d80c9df1.async.js", "https://gw.alipayobjects.com/os/lib/??react/16.13.1/umd/react.production.min.js,react-dom/16.13.1/umd/react-dom.production.min.js,react-dom/16.13.1/umd/react-dom-server.browser.production.min.js,moment/2.24.0/min/moment.min.js", "https://gw.alipayobjects.com/as/g/larkgroup/lake-codemirror/6.0.2/CodeMirror.js", "https://gw.alipayobjects.com/as/g/larkgroup/lark-sheet/11.0.20/lark-sheet.css", "https://gw.alipayobjects.com/a/g/lark/??immutable/3.8.2/immutable.min.js", "https://gw.alipayobjects.com/as/g/larkgroup/lark-sheet/11.0.20/lark-sheet.js"];
self.resourceBase = "https://gw.alipayobjects.com/os/chair-script/skylark/";
self.addEventListener("install", (e => {
//预加载常用资源
Array.isArray(self.assets) && e.waitUntil(caches.open("v1").then((e => {
e.addAll(self.assets)
})))
})), self.addEventListener("activate", (e => {
Array.isArray(self.assets) && caches.open("v1").then((e => {
e.keys().then((t => {
t.forEach((t => {
//过期资源释放
self.assets.includes(t.url) || e.delete(t)
}))
}))
}))
}));
const r = [self.resourceBase, "https://at.alicdn.com/t/", "https://gw.alipayobjects.com/os/"];
self.addEventListener("fetch", (e => {
//拦截资源,满足上述域名,优先使用缓存,否则使用网络下载资源并更新资源。
r.some((t => e.request.url.startsWith(t))) && e.respondWith(caches.match(e.request).then((t => t && 200 === t.status ? t : fetch(e.request).then((t => {
if (200 !== t.status) return t;
const r = t.clone();
return caches.open("v1").then((t => {
t.put(e.request, r)
})), t
})).catch((() => {})))))
}))
缓存、缓存更新、拦截请求
// 缓存静态资源文件列表
let cacheFiles = [
'./test.js',
'./index.html',
'./src/img/yy.png'
]
// serviceworker使用版本
let __version__ = 'cache-v2'
// 缓存静态资源
self.addEventListener('install', function (evt) {
// 强制更新sw.js
self.skipWaiting()
evt.waitUntil(
caches.open(version).then(function (cache) {
return cache.addAll(cacheFiles)
})
)
})
// 缓存更新
self.addEventListener('active', function (evt) {
evt.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (cacheName) {
if (cacheName !== version) {
return caches.delete(cacheName)
}
})
)
})
)
})
// 请求拦截
self.addEventListener('fetch', function (evt) {
console.log('处理fetch事件:', evt.request.url)
evt.respondWith(
caches.match(evt.request).then(function (response) {
if (response) {
console.log('缓存匹配到res:', response)
return response
}
console.log('缓存未匹配对应request,准备从network获取', caches)
return fetch(evt.request).then(function (response) {
console.log('fetch获取到的response:', response)
// 必须是有效请求,必须是同源响应,第三方的请求,因为不可控,最好不要缓存
if (!response || response.status !== 200 || response.type !== 'basic') {
caches.open(version).then(function (cache) {
cache.put(evt.request, response)
})
}
return response;
})
}).catch(function (err) {
console.error('fetch 接口错误', err)
throw err
})
)
})
270

被折叠的 条评论
为什么被折叠?



