Service Worker控制缓存实战

本文详细介绍了Service Worker的生命周期,包括installing、activated、idle和fetch阶段,强调了fetch阶段在缓存策略中的关键作用。通过实际例子展示了如何使用Service Worker进行缓存,并对比了原生实现的复杂性。此外,讨论了预缓存(pre-cache)和运行时缓存(runtime cache)的工作原理,以及不同缓存策略,如staleWhileRevalidate、networkFirst等。文章还提及了知名工具Workbox在简化Service Worker缓存操作方面的应用。
摘要由CSDN通过智能技术生成

前面提到过,由于sw会监听和代理所有的请求,所以sw的作用域就显得额外的重要了,比如说我们只想监听我们专题页的所有请求,就在注册时指定路径:

navigator.serviceWorker.register(‘/topics/sw.js’);

这样就只会对topics/下面的路径进行优化。

installing

我们注册后,浏览器就会开始安装sw,可以通过事件监听:

//service worker安装成功后开始缓存所需的资源

var CACHE_PREFIX = ‘cms-sw-cache’;

var CACHE_VERSION = ‘0.0.20’;

var CACHE_NAME = CACHE_PREFIX+‘-’+CACHE_VERSION;

var allAssets = [

‘./main.css’

];

self.addEventListener(‘install’, function(event) {

//调试时跳过等待过程

self.skipWaiting();

// Perform install steps

//首先 event.waitUntil 你可以理解为 new Promise,

//它接受的实际参数只能是一个 promise,因为,caches 和 cache.addAll 返回的都是 Promise,

//这里就是一个串行的异步加载,当所有加载都成功时,那么 SW 就可以下一步。

//另外,event.waitUntil 还有另外一个重要好处,它可以用来延长一个事件作用的时间,

//这里特别针对于我们 SW 来说,比如我们使用 caches.open 是用来打开指定的缓存,但开启的时候,

//并不是一下就能调用成功,也有可能有一定延迟,由于系统会随时睡眠 SW,所以,为了防止执行中断,

//就需要使用 event.waitUntil 进行捕获。另外,event.waitUntil 会监听所有的异步 promise

//如果其中一个 promise 是 reject 状态,那么该次 event 是失败的。这就导致,我们的 SW 开启失败。

event.waitUntil(

caches.open(CACHE_NAME)

.then(function(cache) {

console.log(‘[SW]: Opened cache’);

return cache.addAll(allAssets);

})

);

});

安装时,sw就开始缓存文件了,会检查所有文件的缓存状态,如果都已经缓存了,则安装成功,进入下一阶段。

activated

如果是第一次加载sw,在安装后,会直接进入activated阶段,而如果sw进行更新,情况就会显得复杂一些。流程如下:

首先老的sw为A,新的sw版本为B。B进入install阶段,而A还处于工作状态,所以B进入waiting阶段。只有等到A被terminated后,B才能正常替换A的工作。

这个terminated的时机有如下几种方式:

1、关闭浏览器一段时间;

2、手动清除serviceworker;

3、在sw安装时直接跳过waiting阶段

//service worker安装成功后开始缓存所需的资源

self.addEventListener(‘install’, function(event) {

//跳过等待过程

self.skipWaiting();

});

然后就进入了activated阶段,激活sw工作。

activated阶段可以做很多有意义的事情,比如更新存储在cache中的key和value:

var CACHE_PREFIX = ‘cms-sw-cache’;

var CACHE_VERSION = ‘0.0.20’;

/**

* 找出对应的其他key并进行删除操作

* @returns {*}

*/

function deleteOldCaches() {

return caches.keys().then(function (keys) {

var all = keys.map(function (key) {

if (key.indexOf(CACHE_PREFIX) !== -1 && key.indexOf(CACHE_VERSION) === -1){

console.log(‘[SW]: Delete cache:’ + key);

return caches.delete(key);

}

});

return Promise.all(all);

});

}

//sw激活阶段,说明上一sw已失效

self.addEventListener(‘activate’, function(event) {

event.waitUntil(

// 遍历 caches 里所有缓存的 keys 值

caches.keys().then(deleteOldCaches)

);

});

idle

这个空闲状态一般是不可见的,这种一般说明sw的事情都处理完毕了,然后处于闲置状态了。

浏览器会周期性的轮询,去释放处于idle的sw占用的资源。

fetch

该阶段是sw最为关键的一个阶段,用于拦截代理所有指定的请求,并进行对应的操作。

所有的缓存部分,都是在该阶段,这里举一个简单的例子:

//监听浏览器的所有fetch请求,对已经缓存的资源使用本地缓存回复

self.addEventListener(‘fetch’, function(event) {

event.respondWith(

caches.match(event.request)

.then(function(response) {

//该fetch请求已经缓存

if (response) {

return response;

}

return fetch(event.request);

}

)

);

});

生命周期大概讲清楚了,我们就以一个具体的例子来说明下原生的serviceworker是如何在生产环境中使用的吧。

举个栗子

我们可以以网易新闻的wap页为例,其针对不怎么变化的静态资源开启了sw缓存,具体的sw.js逻辑和解读如下:

‘use strict’;

//需要缓存的资源列表

var precacheConfig = [

[“https://static.ws.126.net/163/wap/f2e/milk_index/bg_img_sm_minfy.png”,

“c4f55f5a9784ed2093009dadf1e954f9”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/change.png”,

“9af1b102ef784b8ff08567ba25f31d95”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/icon-download.png”,

“1c02c724381d77a1a19ca18925e9b30c”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/icon-login-dark.png”,

“b59ba5abe97ff29855dfa4bd3a7a9f35”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/icon-refresh.png”,

“a5b1084e41939885969a13f8dbc88abd”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/icon-video-play.png”,

“065ff496d7d36345196d254aff027240”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/icon.ico”,

“a14e5365cc2b27ec57e1ab7866c6a228”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/iconfont_1.eot”,

“e4d2788fef09eb0630d66cc7e6b1ab79”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/iconfont_1.svg”,

“d9e57c341608fddd7c140570167bdabb”],

[“https://static.ws.126.net/163/wap/f2e/milk_index/iconfont_1.ttf”,

“f422407038a3180bb3ce941a4a52bfa2”],

[“https://st

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值