Service Worker
我们的应用程序的主进程主要负责渲染dom,执行交互请求,而Service Worker 是浏览器在后台独立于网页运行的,它重新在后台起了一个进程,它和应用的主进程互不影响,可以同时执行。 sw可以拦截和处理网络请求,包括通过程序来管理缓存中的响应。在使用 service-worker 前,我们必须要先在主进程中注册它,然后才能在 service-worker 进程中编写逻辑。
//index.js. 注册SW
if ("serviceWorker" in navigator) {
// Use the window load event to keep the page load performant
window.addEventListener("load", () => {
navigator.serviceWorker.register("/service-worker.js").then(registration=>{
console.log("register succces...")
}, err=>{
console.log("register error...",err)
});
});
}
复制代码
我们在根路径下注册了一个 SW,那SW 就可以拦截对应服务下的所有请求。只需要监听 fetch 事件,你就可以任意的操纵请求,可以返回从 CacheStorage 中读的数据,也可以通过 Fetch API 发起新的请求,甚至可以 new 一个 Response,返回给页面。
service-worker
//service-worker.js 简单输出一些文本
console.log('Hello from service-worker.js');
var cacheStorageKey = 'cachesName';
var cacheList = [
// 注册成功后要立即缓存的资源列表
"/test.css",
"/index.js",
{
url: "/index.html",
revision: "383676" //-- revision 可以通过工具插件workbox-webpack-plugin维护
}
]
// 当浏览器解析完 SW 文件时触发 install 事件 安装SW
self.addEventListener('install', function(e) {
// install 事件中一般会将 cacheList 中要换存的内容通过 addAll 方法,请求一遍放入 caches 中
e.waitUntil(
caches.open(cacheStorageKey).then(function(cache) {
return cache.addAll(cacheList)
})
);
});
// 激活时触发 activate 事件
self.addEventListener('activate', function(e) {
// active 事件中通常做一些过期资源释放的工作,匹配到就从 caches 中删除
var cacheDeletePromises = caches.keys().then(cacheNames => {
return Promise.all(cacheNames.map(name => {
if (name !== cacheStorageKey) {
return caches.delete(name);
} else {
return Promise.resolve();
}
}));
});
e.waitUntil(
Promise.all([cacheDeletePromises])
);
});
// 缓存和返回请求
self.addEventListener('fetch', function(e) {
// 在此编写缓存策略
e.respondWith(
// 可以通过匹配缓存中的资源返回
caches.match(e.request)
// 也可以从远端拉取
fetch(e.request.url)
// 也可以自己造
new Response('hell0')
// 也可以通过吧 fetch 拿到的响应通过 caches.put 方法放进 caches
);
});
复制代码
Workbox
workbox 用于支持离线web apps的js库, 是Google 根据SW的最佳实践推出的官方框架,封装了SW底层的API来监听SW的安装,激活,fetch事件以及缓存等相关逻辑处理,使用起来更简单方便。
- 预缓存
- 运行时缓存np
- 策略(Strategies)
- 请求路由
- 后台同步
- 便捷的调试
- 相比于 sw-precache和 sw-toolbox 具有更大的灵活性和更完备的功能
Workbox 的主要功能是它的路由和缓存策略模块。侦听网页的请求,并根据策略如何缓存和响应请求。这两个功能的具体实现对应于它们的workerbox的workbox.routing ,workbox.strategies 和workbox.precaching。 通过 workbox.routing 模块提供的路由控制和 workbox.strategies 模快提供的缓存策略控制帮助你做动态缓存。通过workbox.precaching 模块来处理 Service Worker 静态资源的预缓存。
缓存策略
利用 workbox.precaching 模块来处理 Service Worker 静态资源的预缓存。
// precache (预缓存) 静态文件 通常项目中的 sw.js 源文件都是通过这样预留一个空数组的方式来预缓存内容列表的
workbox.precaching.precacheAndRoute([
// 注册成功后要立即缓存的资源列表
"/test.css",
"/index.js",
{
url: "/index.html",
revision: "383676" //-- revision 可以通过工具插件workbox-webpack-plugin维护
}
]);
复制代码
路由请求
workbox.routing有3种方式来拦截匹配到的请求
- string
- 正则
- 回调函数
// string
workbox.routing.registerRoute(
'/logo.png',
handler
);
// RegExp
workbox.routing.registerRoute(
new RegExp('\\.js$'),
jsHandler
);
// Callback Function
const matchFunction = ({url, event}) => {
// Return true if the route should match
return false;
};
workbox.routing.registerRoute(
matchFunction,
handler
);
复制代码
上述中的处理函数有两种方式
- 使用workbox.strategies.
- 提供一个Promise的回调函数
然而,利用 workbox.routing 模块提供的路由控制和 workbox.strategies 模快提供的缓存策略控制帮助你做动态缓存。
缓存策略
Stale While Revalidate
这种策略当请求的路由有对应的 Cache 缓存结果就直接返回,在返回 Cache 缓存结果的同时会在后台发起网络请求拿到请求结果并更新 Cache 缓存,如果本来就没有 Cache 缓存的话,直接就发起网络请求并返回结果。
workbox.routing.registerRoute(
match, // 匹配的路由
workbox.strategies.staleWhileRevalidate()
);
复制代码
Network First
这种策略就是当请求路由是被匹配的,就采用网络优先的策略,也就是优先尝试拿到网络请求的返回结果,如果拿到网络请求的结果,就将结果返回给客户端并且写入 Cache 缓存,如果网络请求失败,那最后被缓存的 Cache 缓存结果就会被返回到客户端,这种策略一般适用于返回结果不太固定或对实时性有要求的请求,为网络请求失败进行兜底。
Cache First
这个策略的意思就是当匹配到请求之后直接从 Cache 缓存中取得结果,如果 Cache 缓存中没有结果,那就会发起网络请求,拿到网络请求结果并将结果更新至 Cache 缓存,并将结果返回给客户端。这种策略比较适合结果不怎么变动且对实时性要求不高的请求。
之前的疑问,如果网络请求一直失败的情况, 是和 Stale While Revalidate的动作一样的 ,是发请求,成功之后然后更新缓存,如果第一次也是失败的,缓存中无对应结果,同样也是是发请求,成功之后然后更新缓存。
Network Only
比较直接的策略,直接强制使用正常的网络请求,并将结果返回给客户端,这种策略比较适合对实时性要求非常高的请求。可以像如下方式使用 Network Only 策略:
Cache Only
这个策略也比较直接,直接使用 Cache 缓存的结果,并将结果返回给客户端,这种策略比较适合一上线就不会变的静态资源请求。可以像如下方式使用 Cache Only 策略
tips
-
查看启动的SW
- chrome://inspect/#service-workers查看启动的sw
-
https sw 只工作在安全模式下
- 本地的local和http 模式下sw都注册不成功。
-
Web App Manifest Generator这个工具可以帮助生成 manifest
-
策略
- 静态资源图片等使用 Cache First
- CSS 和 JS, 使用 Stale-While-Revalidate 策略,既保证了页面速度,即便失败,用户刷新一下就更新了
- 不建议使用 Cache only 和 Cache first