UNPKG

@jorsek/ezd-client

Version:
115 lines (86 loc) 3.43 kB
import limiter from "p-limit"; import { Client, INavTree } from "src"; import { Workbox } from "workbox-window"; export const getOfflineStatus = () => { const val = window.localStorage.getItem("prefetch_status"); if (val === "complete") { return "COMPLETE"; } else { return "INCOMPLETE"; } }; export const prefetchAll = async ({ status_callback, client, parallelism = 10 }: { status_callback: (status: string) => void; client: Client; parallelism?: number }) => { if (getOfflineStatus() === "COMPLETE") { status_callback("Ready"); return; } const do_fetch = async () => { const paths = ["/"]; const hidden_fetcher = document.createElement("div"); hidden_fetcher.hidden = true; const limit = limiter(parallelism); const sections = await client.content.getSections(); let processed = 0; let total = 0; const section_promise_map: { [key: string]: Array<Promise<void>> } = {}; const loadLeaf = async (section, leaf: {href: string}) => { try { const content = await client.content.getContent(leaf.href); paths.push(`/content/${leaf.href}`); hidden_fetcher.innerHTML = content.content; processed++; status_callback(`Processing ${section}: ${processed}/${total}`); } catch (e) { // womp womp, still try and load stuff anyway } }; const handleTree = (section, tree: INavTree) => { if (!section_promise_map[section]) { section_promise_map[section] = []; } section_promise_map[section].push(limit(() => loadLeaf(section, tree))); total++; for (const child of tree.children) { handleTree(section, child); } }; for (const section of sections) { const navTree = await client.content.getNavTree(section.href); if (!section_promise_map[section.title]) { section_promise_map[section.title] = []; } section_promise_map[section.title].push(limit(() => loadLeaf(section.title, {href: section.href}))); total++; handleTree(section.title, navTree); } for (const [section_name, promises] of Object.entries(section_promise_map)) { await Promise.all(promises); } return paths; // status_callback("Offline Ready!"); }; const wb = new Workbox("/service-worker.js"); wb.addEventListener("installed", (event) => { // @ts-ignore if (!event.isUpdate) { status_callback("First Service Worker load!"); window.location.reload(); } }); status_callback("Waiting for sw to control page..."); // tslint:disable-next-line: no-floating-promises wb.register(); await wb.controlling; const urlsToCache = await do_fetch(); status_callback(`Prefetching ${urlsToCache.length} content pages...`); // @ts-ignore const success = await wb.messageSW({ type: "CACHE_URLS", payload: { urlsToCache, }, }); status_callback(`Prefetch ${success ? "success" : "failure"}`); window.localStorage.setItem("prefetch_status", "complete"); status_callback("All set!"); };