forked from vercel/next.js
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathnext-prefetcher.js
104 lines (92 loc) · 2.21 KB
/
next-prefetcher.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
/* global self */
const CACHE_NAME = 'next-prefetcher-v1'
const log = () => {}
self.addEventListener('install', () => {
log('Installing Next Prefetcher')
})
self.addEventListener('activate', (e) => {
log('Activated Next Prefetcher')
e.waitUntil(Promise.all([
resetCache(),
notifyClients()
]))
})
self.addEventListener('fetch', (e) => {
e.respondWith(getResponse(e.request))
})
self.addEventListener('message', (e) => {
switch (e.data.action) {
case 'ADD_URL': {
log('CACHING ', e.data.url)
sendReply(e, cacheUrl(e.data.url))
break
}
case 'RESET': {
log('RESET')
sendReply(e, resetCache())
break
}
default:
console.error('Unknown action: ' + e.data.action)
}
})
function sendReply (e, result) {
const payload = { action: 'REPLY', actionType: e.data.action, replyFor: e.data.id }
result
.then((result) => {
payload.result = result
e.source.postMessage(payload)
})
.catch((error) => {
payload.error = error.message
e.source.postMessage(payload)
})
}
function cacheUrl (url) {
const req = new self.Request(url, {
mode: 'no-cors',
headers: {
'Accept': 'application/json'
}
})
return self.caches.open(CACHE_NAME)
.then((cache) => {
return self.fetch(req)
.then((res) => cache.put(req, res))
})
}
function getResponse (req) {
return self.caches.open(CACHE_NAME)
.then((cache) => cache.match(req))
.then((res) => {
if (res) {
log('CACHE HIT: ' + req.url)
return res
} else {
log('CACHE MISS: ' + req.url)
return self.fetch(req)
}
})
}
function resetCache () {
let cache
return self.caches.open(CACHE_NAME)
.then((c) => {
cache = c
return cache.keys()
})
.then(function (items) {
const deleteAll = items.map((item) => cache.delete(item))
return Promise.all(deleteAll)
})
}
function notifyClients () {
return self.clients.claim()
.then(() => self.clients.matchAll())
.then((clients) => {
const notifyAll = clients.map((client) => {
return client.postMessage({ action: 'NEXT_PREFETCHER_ACTIVATED' })
})
return Promise.all(notifyAll)
})
}