-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add simple service worker (#98)
- Loading branch information
Showing
2 changed files
with
93 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
const addResourcesToCache = async (resources) => { | ||
const cache = await caches.open('v1'); | ||
await cache.addAll(resources); | ||
}; | ||
|
||
const putInCache = async (request, response) => { | ||
const cache = await caches.open('v1'); | ||
await cache.put(request, response); | ||
}; | ||
|
||
const cacheFirst = async ({ request, preloadResponsePromise, fallbackUrl }) => { | ||
// First try to get the resource from the cache | ||
const responseFromCache = await caches.match(request); | ||
if (responseFromCache) { | ||
return responseFromCache; | ||
} | ||
|
||
// Next try to use the preloaded response, if it's there | ||
// NOTE: Chrome throws errors regarding preloadResponse, see: | ||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1420515 | ||
// https://github.com/mdn/dom-examples/issues/145 | ||
// To avoid those errors, remove or comment out this block of preloadResponse | ||
// code along with enableNavigationPreload() and the "activate" listener. | ||
const preloadResponse = await preloadResponsePromise; | ||
if (preloadResponse) { | ||
console.info('using preload response', preloadResponse); | ||
putInCache(request, preloadResponse.clone()); | ||
return preloadResponse; | ||
} | ||
|
||
// Next try to get the resource from the network | ||
try { | ||
const responseFromNetwork = await fetch(request.clone()); | ||
// response may be used only once | ||
// we need to save clone to put one copy in cache | ||
// and serve second one | ||
putInCache(request, responseFromNetwork.clone()); | ||
return responseFromNetwork; | ||
} catch (error) { | ||
const fallbackResponse = await caches.match(fallbackUrl); | ||
if (fallbackResponse) { | ||
return fallbackResponse; | ||
} | ||
// when even the fallback response is not available, | ||
// there is nothing we can do, but we must always | ||
// return a Response object | ||
return new Response('Network error happened', { | ||
status: 408, | ||
headers: { 'Content-Type': 'text/plain' }, | ||
}); | ||
} | ||
}; | ||
|
||
const enableNavigationPreload = async () => { | ||
if (self.registration.navigationPreload) { | ||
// Enable navigation preloads! | ||
await self.registration.navigationPreload.enable(); | ||
} | ||
}; | ||
|
||
self.addEventListener('activate', (event) => { | ||
event.waitUntil(enableNavigationPreload()); | ||
}); | ||
|
||
self.addEventListener('install', (event) => { | ||
event.waitUntil( | ||
addResourcesToCache([ | ||
'./', | ||
'./index.html', | ||
'./favicon.ico' | ||
]) | ||
); | ||
}); | ||
|
||
self.addEventListener('fetch', (event) => { | ||
event.respondWith( | ||
cacheFirst({ | ||
request: event.request, | ||
preloadResponsePromise: event.preloadResponse, | ||
fallbackUrl: './index.html', | ||
}) | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters