Created
October 6, 2019 16:54
-
-
Save jeffposnick/8b3465e933275f15e6cb1ce6737403c0 to your computer and use it in GitHub Desktop.
Workbox CDN + JS service worker migrated to a custom bundle + TS equivalent
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
import {CacheFirst, NetworkOnly} from 'workbox-strategies'; | |
import {cacheNames} from 'workbox-core'; | |
import {cleanupOutdatedCaches, getCacheKeyForURL, precacheAndRoute} from 'workbox-precaching'; | |
import {ExpirationPlugin} from 'workbox-expiration'; | |
import {initialize as initializeOfflineAnalytics} from 'workbox-google-analytics'; | |
import {registerRoute, setCatchHandler} from 'workbox-routing'; | |
import {RouteHandlerCallbackOptions} from 'workbox-core/types'; | |
import {skipWaiting} from 'workbox-core'; | |
import nunjucks from 'nunjucks/browser/nunjucks'; | |
precacheAndRoute(self.__WB_MANIFEST); | |
cleanupOutdatedCaches(); | |
async function getPrecachedResponse(url: string) { | |
const cacheKey = getCacheKeyForURL(url); | |
if (!cacheKey) { | |
throw new Error(`${url} is not in the precache manifest.`); | |
} | |
const cache = await caches.open(cacheNames.precache); | |
const cachedResponse = await cache.match(cacheKey); | |
if (!cachedResponse) { | |
throw new Error(`${url} is not precached.`); | |
} | |
return cachedResponse; | |
} | |
const CacheStorageLoader = nunjucks.Loader.extend({ | |
async: true, | |
getSource: async function(name: string, callback: Function) { | |
try { | |
const path = `/_posts/_includes/${name}`; | |
const cachedResponse = await getPrecachedResponse(path); | |
const src = await cachedResponse.text(); | |
callback(null, {src, path, noCache: false}); | |
} catch(error) { | |
callback(error); | |
} | |
} | |
}); | |
const nunjucksEnv = new nunjucks.Environment( | |
new CacheStorageLoader() | |
); | |
let _site: {string: any}; | |
async function getSiteData() { | |
if (!_site) { | |
const siteDataResponse = await getPrecachedResponse('/_posts/_data/site.json'); | |
_site = await siteDataResponse.json(); | |
} | |
return _site; | |
} | |
const postHandler = async (options: RouteHandlerCallbackOptions) => { | |
const {params} = options; | |
if (!(params && Array.isArray(params))) { | |
throw new Error(`Couldn't get parameters from router.`); | |
} | |
const site = await getSiteData(); | |
// params[3] corresponds to post.fileSlug in 11ty. | |
const cachedResponse = await getPrecachedResponse(`/_posts/${params[3]}.json`); | |
const context = await cachedResponse.json(); | |
context.site = site; | |
context.content = context.html; | |
const html: string = await new Promise((resolve, reject) => { | |
nunjucksEnv.render( | |
context.layout, | |
context, | |
(error: Error | undefined, html: string) => { | |
if (error) { | |
return reject(error); | |
} | |
return resolve(html); | |
} | |
); | |
}); | |
const headers = { | |
'content-type': 'text/html', | |
}; | |
return new Response(html, {headers}); | |
}; | |
registerRoute( | |
new RegExp('/(\\d{4})/(\\d{2})/(\\d{2})/(.+)\\.html'), | |
postHandler | |
); | |
registerRoute( | |
new RegExp('/assets/images/'), | |
new CacheFirst({ | |
cacheName: 'images', | |
plugins: [ | |
new ExpirationPlugin({ | |
maxEntries: 20, | |
}), | |
], | |
}) | |
); | |
// If anything goes wrong when handling a route, return the network response. | |
setCatchHandler(new NetworkOnly()); | |
initializeOfflineAnalytics(); | |
skipWaiting(); |
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
importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.0.0-alpha.1/workbox-sw.js'); | |
importScripts('https://cdn.jsdelivr.net/npm/[email protected]/browser/nunjucks.min.js'); | |
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST); | |
workbox.precaching.cleanupOutdatedCaches(); | |
const CacheStorageLoader = nunjucks.Loader.extend({ | |
async: true, | |
getSource: async function(name, callback) { | |
try { | |
const path = `/_posts/_includes/${name}`; | |
const cachedResponse = await caches.match( | |
workbox.precaching.getCacheKeyForURL(path), { | |
cacheName: workbox.core.cacheNames.precache, | |
} | |
); | |
const src = await cachedResponse.text(); | |
callback(null, {src, path, noCache: false}); | |
} catch(error) { | |
callback(error); | |
} | |
} | |
}); | |
const nunjucksEnv = new nunjucks.Environment( | |
new CacheStorageLoader() | |
); | |
let _site; | |
async function initSiteData() { | |
if (!_site) { | |
const siteDataResponse = await caches.match( | |
workbox.precaching.getCacheKeyForURL('/_posts/_data/site.json'), { | |
cacheName: workbox.core.cacheNames.precache, | |
} | |
); | |
_site = await siteDataResponse.json(); | |
} | |
return _site; | |
} | |
const postHandler = async ({params}) => { | |
const site = await initSiteData(); | |
// params[3] corresponds to post.fileSlug in 11ty. | |
const cachedResponse = await caches.match( | |
workbox.precaching.getCacheKeyForURL(`/_posts/${params[3]}.json`), { | |
cacheName: workbox.core.cacheNames.precache, | |
} | |
); | |
const context = await cachedResponse.json(); | |
context.site = site; | |
context.content = context.html; | |
const html = await new Promise((resolve, reject) => { | |
nunjucksEnv.render( | |
context.layout, | |
context, | |
(error, html) => { | |
if (error) { | |
return reject(error); | |
} | |
return resolve(html); | |
} | |
); | |
}); | |
const headers = { | |
'content-type': 'text/html', | |
}; | |
return new Response(html, {headers}); | |
}; | |
workbox.routing.registerRoute( | |
new RegExp('/(\\d{4})/(\\d{2})/(\\d{2})/(.+)\\.html'), | |
postHandler | |
); | |
workbox.routing.registerRoute( | |
new RegExp('/assets/images/'), | |
new workbox.strategies.CacheFirst({ | |
cacheName: 'images', | |
plugins: [ | |
new workbox.expiration.Plugin({ | |
maxEntries: 20, | |
}), | |
], | |
}) | |
); | |
workbox.routing.registerRoute( | |
new RegExp('https://storage\\.googleapis\\.com/workbox-cdn/releases/.+/workbox-window\\.prod\\.mjs'), | |
new workbox.strategies.CacheFirst() | |
); | |
// If anything goes wrong when handling a route, return the network response. | |
workbox.routing.setCatchHandler(new workbox.strategies.NetworkOnly()); | |
workbox.googleAnalytics.initialize(); | |
workbox.core.skipWaiting(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment