Service worker是一个注册在指定源和路径下的事件驱动worker。它采用JavaScript控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。
Service worker运行在worker上下文,因此它不能访问DOM。相对于驱动应用的主JavaScript线程,它运行在其他线程中,所以不会造成阻塞。它设计为完全异步,同步API(如XHR和localStorage)不能在service worker中使用。
出于安全考量,Service workers只能由HTTPS承载,毕竟修改网络请求的能力暴露给中间人攻击会非常危险。在Firefox浏览器的用户隐私模式,Service Worker不可用。
如何使用如下:
1、html 引入代码非https不能使用
if ('serviceWorker' in navigator && location.protocol == 'https:') {
navigator.serviceWorker.register('/serviceWorker.js?v=201911281608')
}
注意version 每次更新如何要替换版本来控制serviecWorker.js 文件的更新
2、serviceWorker.js 代码如何下
// 当前缓存版本的唯一标识符,用当前时间代替
var VERSION = "201911281608"
// 当前缓存白名单,在新脚本的 install 事件里将使用白名单里的 key
var cacheFileList = [
"staticPath/static/??vue/2.6.10/index.js,js/1.0.0/polyfill/index.js",
"staticPath/static/??js/1.0.1/utils/index.js,js/1.0.1/ajax/index.js,js/1.0.0/store/index.js,js/1.0.1/request/index.js,js/1.0.5/scale/index.js",
"staticPath/static/??js/1.0.3/toast/index.js,js/1.0.1/loading/index.js",
"staticPath/static/??css/1.1.1/main.css,css/1.1.1/ui-component.css"
]
self.addEventListener('install', (event) => {
// 等待所有资源缓存完成时,才可以进行下一步
event.waitUntil(
caches.open(VERSION)
.then((cache) => {
// 要缓存的文件 URL 列表
return cache.addAll(cacheFileList)
})
.then(() => self.skipWaiting())
.then(() => console.log('installation complete! version: ' + VERSION))
)
})
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames
.filter(key => !key.startsWith(VERSION)) // 过滤不需要删除的资源
.map(key => caches.delete(key)) // 删除旧版本资源,返回为 Promise 对象
)
}).then(() => {
console.log('removeOldCache completed.');
})
)
})
var isCORSRequest = function(url) {
return url.indexOf(location.host) === -1
}
var isNeedCache = function(url) {
var CACHE_HOST = ['img.piaoniu.com', 'm.img.whqietu.com', 'm.static.whqietu.com', 'assets.piaoniu.com']
return CACHE_HOST.some((host) => {
return url.indexOf(host) !== -1
})
}
self.addEventListener('fetch',(event) => {
var url = event.request.url
// Ignore not GET https request.
if (event.request.method !== 'GET' || new URL(url).protocol !== 'https:' || !isNeedCache(url)) {
return
}
var request = isCORSRequest(url) ? new Request(url, {mode: 'cors'}) : event.request
event.respondWith(
caches.match(request)
.then((response) => {
if (response) {
return response
}
// 因为 event.request 流已经在 caches.match 中使用过一次,
// 那么该流是不能再次使用的。我们只能得到它的副本,拿去使用。
var fetchRequest = request.clone()
// fetch 的通过信方式,得到 Request 对象,然后发送请求
return fetch(fetchRequest)
.then((httpRes) => {
// 检查是否成功
if(!httpRes || httpRes.status !== 200 || (httpRes.type !== 'basic' && httpRes.type !== 'cors')) {
return httpRes
}
// 如果成功,该 response 一是要拿给浏览器渲染,而是要进行缓存。
// 不过需要记住,由于 caches.put 使用的是文件的响应流,一旦使用,
// 那么返回的 response 就无法访问造成失败,所以,这里需要复制一份。
var responseToCache = httpRes.clone()
caches.open(VERSION)
.then((cache) => {
cache.put(request, responseToCache)
})
return httpRes
}
)
})
)
})