My Little World

service worker

前端与后台代理服务器

主要方法

fetch 事件/方法:service worker向后台发起HTTP请求的方法
fetch(url).then()

message事件/方法:页面和service worker之间进行通信的方法;同一页面两个窗口之间通信(web worker线程)
postMessage发送消息;message接收消息

caches API:处理缓存

生命周期

注册 register
安装 install
激活 activation
更新 Update
service-worker.js文件更新被浏览器发现后,会进入waitting等待状态,当前页面依旧使用旧文件进行work,
直到当前页面关闭,旧版本文件的service worker才会被kill掉,新版本文件的service worker开始接管页面的缓存资源
新的service worker一开始接管就会触发activate事件,从而可以做一些上次老版本缓存的工作

缓存的文件发生更新,可以在fetch 的时候,一边检查更新从而更新缓存,一边检查缓存然后fetch新资源给浏览器,
通过 promise 的 resolve 特性来决定谁快

应用场景

(https环境)
后台消息传递
网络代理,转发请求,伪造响应
离线缓存
消息推送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//在项目入口/配置js文件 进行注册
if (navigator.serviceWorker) {
navigator.serviceWorker.register('service-worker.js').then(function(registration) {
console.log('service worker 注册成功');
}).catch(function (err) {
console.log('servcie worker 注册失败')
});
}

//service-worker.js 放在项目根目录下,service worker的执行代码
var cacheFiles = [ //指定缓存的文件
'about.js',
'blog.js'
];
self.addEventListener('install', function (evt) { //在安装的时候就将指定文件存入cache storage中
evt.waitUntil(
caches.open('my-test-cahce-v1').then(function (cache) { //使用caches api进行缓存操作
return cache.addAll(cacheFiles);
})
);
});
//页面fetch 资源时进行过滤
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request) //检查缓存是否有资源
.then(function(response) {
if (response) { //如果有直接返回
return response;
}

// 因为 event.request 流已经在 caches.match 中使用过一次,
// 那么该流是不能再次使用的。我们只能得到它的副本,拿去使用。
var fetchRequest = event.request.clone();

// fetch 的通过信方式,得到 Request 对象,然后发送请求
return fetch(fetchRequest).then(
function(response) {
// 检查是否成功
if(!response || response.status !== 200 || response.type !== 'basic') {
return response;
}

// 如果成功,该 response 一是要拿给浏览器渲染,而是要进行缓存。
// 由于 caches.put 使用的是文件的响应流,一旦使用,
// 那么返回的 response 就无法访问造成失败,所以,这里需要复制一份。
var responseToCache = response.clone();

caches.open(CACHE_NAME)
.then(function(cache) {
cache.put(event.request, responseToCache);
});

return response;
}
);
})
);
});

//service-worker.js文件更新删除之前版本文件缓存的资源

self.addEventListener('activate', function(event) {

var cacheWhitelist = ['v1'];

event.waitUntil(
// 遍历 caches 里所有缓存的 keys 值
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (cacheWhitelist.includes(cacheName)) {
// 删除 v1 版本缓存的文件
return caches.delete(cacheName);
}
})
);
})
);
});

相关文档
fetch 通信
web worker 语法
Service Worker API

遗留问题:fetch通信headers添加token字段,不生效