/
Cache.js
106 lines (89 loc) · 3.91 KB
/
Cache.js
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import WorkerStorage from './lib/WorkerStorage';
import { ServiceWorker } from './index';
import InjectionReceiver from '../core/InjectionReceiver';
const FIVE_MINUTES = 1000 * 60 * 5;
export const CacheMeta = {
__proto__: InjectionReceiver,
};
const meta = CacheMeta.constructor();
// [meta*]
export const Cache = {
register(manifestUrl) {
return fetch(manifestUrl)
.then(response => response.json())
.then(manifest => Promise.all([caches.open(manifest.name), manifest]))
.then(([cache, manifest]) => [manifest, cache.addAll(manifest.staticFiles)])
.then(([manifest]) => {
WorkerStorage.write('config', { key: 'cacheName', value: manifest.name });
WorkerStorage.write('config', { key: 'cacheUpdate', value: Date.now() });
WorkerStorage.write('config', { key: 'cacheUrl', value: manifestUrl });
WorkerStorage.write('config', { key: 'staticFileBuildId', value: manifest.buildId });
});
},
cleanUp() {
return Promise.all([
caches.keys(),
WorkerStorage.read('config').where('key').equals('cacheName').get()
]).then(([keys, [currentKey]]) => keys.forEach(key => key !== currentKey.value && caches.delete(key)));
},
init() {
return WorkerStorage.read('config')
.where('key').equals('cacheUpdate')
.or('key').equals('staticFileBuildId')
.or('key').equals('cacheUrl')
.get().then(([cacheUpdate, staticFileBuildId, cacheUrl]) => {
if (!cacheUpdate || !staticFileBuildId || !cacheUrl) {
return Promise.reject();
}
if ((Date.now() - cacheUpdate.value) < FIVE_MINUTES) {
return;
}
return fetch(cacheUrl.value)
.then(response => response.json())
.then(manifest => {
if (manifest.buildId > staticFileBuildId.value) {
console.log('[SW] updating static files...');
return Promise.all([manifest, caches.open(manifest.name)]);
}
return Promise.reject();
})
.then(([manifest, cache]) => cache.addAll(manifest.staticFiles))
.then(() => meta.injected(ServiceWorker).emit('update-available'))
.catch((error) => error && console.error(error));
});
},
matchStatic(request) {
const requestUrl = request.url.replace(/#.*$/, '');
let indexRequest = null;
if (requestUrl.search(/\/$/) > -1) {
indexRequest = new Request(`${requestUrl }index.html`, {
method: request.method,
body: request.body,
mode: (request.mode === 'navigate' ? 'cors' : request.mode),
credentials: request.credentials,
redirect: request.redirect,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
integrity: request.integrity,
cache: request.cache,
keepalive: request.keepalive,
signal: request.signal,
});
}
return WorkerStorage.read('config').where('key').equals('cacheName').get()
.then(cacheName => {
const queries = [];
queries.push(caches.match(request, {
ignoreSearch: true,
cacheName: cacheName.value
}));
if (indexRequest) {
queries.push(caches.match(indexRequest, {
cacheName: cacheName.value,
}));
}
return Promise.all(queries);
}).then(responses => responses.find(item => !!item));
}
};
export default Cache;