基本知识
service worker(sw)
- 是事件驱动的worker,那么具有web worker特性(如:不能访问DOM;独立于js执行线程等)
- 充当web应用、浏览器和网络之间的代理,具有缓冲资源、fetch、push、background sync、postMessage等能力
- 只能运行于https和localhost环境下
sw声明周期
- installing:发生在sw注册之后,开始安装,触发install事件
- installed:sw已经安装完了
- activating:触发activate事件
- activated:更新缓冲的时机
- redundant:sw生命周期结束
sw事件
- install:在该事件回调中可以指定要缓冲的静态资源
- activate:预处理:更新、清除无用的缓冲
- message: 可以通过postMessage API与主线程通信
- fetch:在这一事件中可以处理请求和缓冲(cache first、network first、network only等)
- push
- sync
workbox
由于sw借助于cache、indexDB存储资源,而这两个API较复杂,Google推出workbox来解决静态资源和请求结果的本地存储 包括plugin、routing、Strategies以及打包构建插件(如webpack插件workbox-webpack-plugin)
缓冲策略
-
Stale While Revalidate
- cache中是否有请求的资源, yes走2,no走3
- 将cache结果返回,走3
- 发起网络请求,拿到请求结果返回的同时并更新 Cache
非常安全的策略,能最快拿到请求的结果,但是会有网络请求占用了用户的网络带宽
``` workbox.routing.registerRoute( match, // 匹配的路由 workbox.strategies.staleWhileRevalidate() ); ``` -
Network First
- 发起网络请求, 成功走2,失败走3
- 返回请求结果的同时并更新 cache
- 将cache缓冲的结果返回
适用于返回结果不太固定或对实时性有要求的请求,并对网络异常进行兜底
``` workbox.routing.registerRoute( match, // 匹配的路由 workbox.strategies.networkFirst() ); ``` -
Cache First
- cache中是否有请求的资源, yes走2,no走3
- 将cache结果返回
- 发起网络请求,拿到请求结果返回的同时并更新 Cache
适用于返回结果固定或对实时性要求不高的请求
``` workbox.routing.registerRoute( match, // 匹配的路由 workbox.strategies.cacheFirst() ); ``` -
Network Only
只能使用网络请求,适用于实时性要求很高的请求
workbox.routing.registerRoute( match, // 匹配的路由 workbox.strategies.networkOnly() ); -
Cache Only
直接使用cache缓冲的结果,适用于不会发生变化的静态资源(如:图片)
workbox.routing.registerRoute( match, // 匹配的路由 workbox.strategies.networkOnly() );
路由该怎么配置呢?
-
完整url(如:第三方资源)
'https://api.map.baidu.com/api?v=3.0&ak=dASz7ubuSpHidP1oQWKuAK3q' -
正则表达式
new RegExp('https://maponline[0-9]\\.bdimg\\.com.*/tile/.*') -
函数
const matchCb = ({ url }) => { return /(statics|js|css)\/(.*)\.(js|css|png|jpg|jpeg|svg|gif)/.test(url) }
如何接入sw
- webpack配置
const {InjectManifest} = require('workbox-webpack-plugin');
// webpack的plugin中添加
new InjectManifest({
swDest: 'sw.js',
swSrc: path.resolve(__dirname, '../sw.js'),
})
- 注册一个Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js');
}
- 如何编写sw.js
importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.0.0-alpha.3/workbox-sw.js');
if (workbox) {
// 设置cache名和版本
workbox.core.setCacheNameDetails({
prefix: 'my-app',
suffix: 'v1'
});
// 使当前sw成为activating状态
workbox.core.skipWaiting()
// 使当前版本的sw在所有的页面中均生效
workbox.core.clientsClaim()
/**
定义缓冲策略:
1. workbox.cacheableResponse:定义资源只有在网络请求成功后才存储
2. workbox.expiration: 设置一个存储资源的数量和有效期限
3. cacheName:设置存储与cache中cache名字
*/
workbox.routing.registerRoute(
'https://api.map.baidu.com/api?v=3.0&ak=dASz7ubuSpHidP1oQWKuAK3q',
new workbox.strategies.CacheFirst({
cacheName: 'baidu',
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200],
}),
new workbox.expiration.Plugin({
maxEntries: 20,
maxAgeSeconds: 7 * 24 * 60 * 60,
}),
],
})
)
}