WIP
This commit is contained in:
commit
844f86cda0
99 files changed
+53591
No files matched your search
+186
@@ -0,0 +1,186 @@
|
||||
// Generated by render_books.py -- do not edit by hand.
|
||||
//
|
||||
// STRATEGY decides what a same-origin GET does:
|
||||
//
|
||||
// network-first ask the network, fall back to the cache when it fails.
|
||||
// Offline, fetch rejects immediately, so the fallback is
|
||||
// effectively instant -- the only cost is one round trip
|
||||
// while online, and you never see a stale page.
|
||||
// cache-first answer from the cache the moment there is a hit. Fastest
|
||||
// possible load, but a rebuild needs two reloads to appear.
|
||||
//
|
||||
// Either way every response that arrives is written back to the cache, so the
|
||||
// offline copy stays current, and a new build changes VERSION, dropping the
|
||||
// caches belonging to older builds.
|
||||
const STRATEGY = 'network-first';
|
||||
const NETWORK_TIMEOUT_MS = 3000;
|
||||
const VERSION = 'c5d29c3cdf15';
|
||||
const CACHE = 'bible-' + VERSION;
|
||||
const ASSETS = [
|
||||
"./",
|
||||
"./1CH.html",
|
||||
"./1CO.html",
|
||||
"./1ES.html",
|
||||
"./1JN.html",
|
||||
"./1KI.html",
|
||||
"./1MA.html",
|
||||
"./1PE.html",
|
||||
"./1SA.html",
|
||||
"./1TH.html",
|
||||
"./1TI.html",
|
||||
"./2CH.html",
|
||||
"./2CO.html",
|
||||
"./2ES.html",
|
||||
"./2JN.html",
|
||||
"./2KI.html",
|
||||
"./2MA.html",
|
||||
"./2PE.html",
|
||||
"./2SA.html",
|
||||
"./2TH.html",
|
||||
"./2TI.html",
|
||||
"./3JN.html",
|
||||
"./3MA.html",
|
||||
"./4MA.html",
|
||||
"./ACT.html",
|
||||
"./AMO.html",
|
||||
"./BAR.html",
|
||||
"./COL.html",
|
||||
"./DAG.html",
|
||||
"./DAN.html",
|
||||
"./DEU.html",
|
||||
"./ECC.html",
|
||||
"./EPH.html",
|
||||
"./ESG.html",
|
||||
"./EST.html",
|
||||
"./EXO.html",
|
||||
"./EZK.html",
|
||||
"./EZR.html",
|
||||
"./FRT.html",
|
||||
"./GAL.html",
|
||||
"./GEN.html",
|
||||
"./GLO.html",
|
||||
"./HAB.html",
|
||||
"./HAG.html",
|
||||
"./HEB.html",
|
||||
"./HOS.html",
|
||||
"./ISA.html",
|
||||
"./JAS.html",
|
||||
"./JDG.html",
|
||||
"./JDT.html",
|
||||
"./JER.html",
|
||||
"./JHN.html",
|
||||
"./JOB.html",
|
||||
"./JOL.html",
|
||||
"./JON.html",
|
||||
"./JOS.html",
|
||||
"./JUD.html",
|
||||
"./LAM.html",
|
||||
"./LEV.html",
|
||||
"./LUK.html",
|
||||
"./MAL.html",
|
||||
"./MAN.html",
|
||||
"./MAT.html",
|
||||
"./MIC.html",
|
||||
"./MRK.html",
|
||||
"./NAM.html",
|
||||
"./NEH.html",
|
||||
"./NUM.html",
|
||||
"./OBA.html",
|
||||
"./PHM.html",
|
||||
"./PHP.html",
|
||||
"./PRO.html",
|
||||
"./PS2.html",
|
||||
"./PSA.html",
|
||||
"./REV.html",
|
||||
"./ROM.html",
|
||||
"./RUT.html",
|
||||
"./SIR.html",
|
||||
"./SNG.html",
|
||||
"./TIT.html",
|
||||
"./TOB.html",
|
||||
"./WIS.html",
|
||||
"./ZEC.html",
|
||||
"./ZEP.html",
|
||||
"./app.js",
|
||||
"./bible.css",
|
||||
"./icons/apple-touch-icon.png",
|
||||
"./icons/icon-192.png",
|
||||
"./icons/icon-512.png",
|
||||
"./index.html",
|
||||
"./manifest.webmanifest"
|
||||
];
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil((async () => {
|
||||
const cache = await caches.open(CACHE);
|
||||
// Added one at a time rather than addAll(): addAll is atomic, so a single
|
||||
// failed asset would leave the app with no offline copy at all.
|
||||
let failed = 0;
|
||||
await Promise.all(ASSETS.map((url) =>
|
||||
cache.add(new Request(url, { cache: 'reload' })).catch(() => { failed++; })));
|
||||
if (failed) console.warn('precache: ' + failed + ' of ' + ASSETS.length + ' failed');
|
||||
await self.skipWaiting();
|
||||
})());
|
||||
});
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil((async () => {
|
||||
const keys = await caches.keys();
|
||||
await Promise.all(keys
|
||||
.filter((k) => k.startsWith('bible-') && k !== CACHE)
|
||||
.map((k) => caches.delete(k)));
|
||||
await self.clients.claim();
|
||||
})());
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
const req = event.request;
|
||||
if (req.method !== 'GET') return;
|
||||
if (new URL(req.url).origin !== location.origin) return;
|
||||
event.respondWith(respond(event));
|
||||
});
|
||||
|
||||
// Aborted rather than raced, so a hung request is actually torn down instead
|
||||
// of leaking while the cache answers.
|
||||
async function fromNetwork(req) {
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), NETWORK_TIMEOUT_MS);
|
||||
try {
|
||||
return await fetch(req, { signal: controller.signal });
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
|
||||
function cached(req) {
|
||||
return caches.match(req, { ignoreSearch: true });
|
||||
}
|
||||
|
||||
async function respond(event) {
|
||||
const req = event.request;
|
||||
|
||||
if (STRATEGY === 'cache-first') {
|
||||
const hit = await cached(req);
|
||||
if (hit) return hit;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fromNetwork(req);
|
||||
if (res && res.ok && res.type === 'basic') {
|
||||
const copy = res.clone();
|
||||
// Not awaited: the response should not wait on the cache write.
|
||||
event.waitUntil(caches.open(CACHE).then((c) => c.put(req, copy)));
|
||||
}
|
||||
return res;
|
||||
} catch (err) {
|
||||
const hit = await cached(req);
|
||||
if (hit) return hit;
|
||||
// Offline and never cached. Navigations get the index rather than the
|
||||
// browser's error page; anything else genuinely fails.
|
||||
if (req.mode === 'navigate') {
|
||||
const index = await cached('./index.html');
|
||||
if (index) return index;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user