1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00
next.js/client/next-prefetcher.js
Arunoda Susiripala 0d2af801ec Use service-worker to fetch only JSON pages. (#924)
* Use service-worker to fetch only JSON pages.
We simply don't need to proxy other requests through that.
That's might cause some latency issues.

* Use a better regexp to identify JSON pages.
2017-01-30 19:42:49 +09:00

108 lines
2.3 KiB
JavaScript

/* 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) => {
// bypass all requests except JSON pages.
if (!(/\/_next\/[^/]+\/pages\//.test(e.request.url))) return
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)
})
}