基本特性
- 不能直接访问/操作 DOM(只能使用特定的 API:Promise、Fetch API、Cache API)
- 需要时直接唤醒,不需要时自动休眠
- 离线缓存内容开发者可控
- 一旦被安装则永远存活,除非手动卸载
- 必须在 HTTPS 环境下工作(本地环境 localhost 除外)
- 广泛使用了 Promise
使用
- 生命周期相关知识
- install 阶段缓存文件列表
- activate 阶段清理缓存
- fetch 拦截请求
注册
main.html 下
// 同域下允许注册多个不同 scope 的 service worker
if ('serviceWorker' in navigator) {
// 缩短白屏时间
window.addEventListener('load', function () {
// scope:指定访问的域
navigator.serviceWorker.register('/static/sw-demo.js', { scope: '/static' })
.then(registration => { // 注册成功
console.log(registration.scope);
})
.catch(error => { // 注册失败
})
})
}
安装
sw-demo.js 下
const myCache = {
NAME: 'my-cache-v0',
data: [
'/',
'/test.js',
'test.css'
]
}
this.addEventListener('install', function (event) {
// 控制安装阶段流程,只有里面的 resolve 了,安装阶段才结束
event.waitUntill(
caches.open(myCache.NAME) // 开辟缓存区
.then(cache => {
// 缓存指定文件列表(注意文件缓存列表过长,会增加缓存失败的概率)
return cache.addAll(myCache.data)
})
)
})
激活
sw-demo.js 下
this.addEventListener('activate', function (event) {
// 控制激活阶段流程,只有里面的 resolve 了,激活阶段才结束
event.waitUntill(
Promise.all([
// 跳过刷新页面的过程,让其立即具备所有的正常功能
this.clients.claim(),
caches.then((cacheList) => {
return Promise.all(
cacheList.map(cacheName => {
// 监测缓存如果不匹配则丢弃缓存
if (cacheName !== myCache.NAME) {
return caches.delete(cacheName)
}
})
)
})
])
)
})
成熟缓存工具
- sw-precache 预缓存
- sw-toolbox 动态缓存
- workbox 集大成者