UNPKG

next-era

Version:

Welcome to **Next Era**! A comprehensive library designed to supercharge your **Next.js** applications with powerful utilities and significant performance optimizations. Build faster, more efficient, and feature-rich Next.js projects with ease.

194 lines (193 loc) 8.04 kB
"use strict"; const CACHE_NAME = "v1"; /// <reference path="https://developer.chrome.com/docs/workbox/caching-strategies-overview" /> const STRATEGY = { CACHE_FIRST: async ({ request, preloadResponsePromise, fallbackUrl, event, }) => { console.debug("[Service Worker][CF] Fetching URL: ", event.request.url); // First try to get the resource from the cache const responseFromCache = await caches.match(request); if (responseFromCache) { return responseFromCache; } // Next try to use (and cache) the preloaded response, if it's there const preloadResponse = await preloadResponsePromise; if (preloadResponse) { event.waitUntil(putInCache(request, preloadResponse.clone())); return preloadResponse; } // Next try to get the resource from the network try { const responseFromNetwork = await fetch(request); // response may be used only once // we need to save clone to put one copy in cache // and serve second one event.waitUntil(putInCache(request, responseFromNetwork.clone())); return responseFromNetwork; } catch { 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" }, }); } }, NETWORK_FIRST: async ({ request, preloadResponsePromise, fallbackUrl, event, }) => { console.debug("[Service Worker][NF] Fetching URL: ", event.request.url); // Next try to use (and cache) the preloaded response, if it's there const preloadResponse = await preloadResponsePromise; if (preloadResponse) { event.waitUntil(putInCache(request, preloadResponse.clone())); return preloadResponse; } // Next try to get the resource from the network try { const responseFromNetwork = await fetch(request); // response may be used only once // we need to save clone to put one copy in cache // and serve second one event.waitUntil(putInCache(request, responseFromNetwork.clone())); return responseFromNetwork; } catch { const fallbackFromCache = await caches.match(request); if (fallbackFromCache) { return fallbackFromCache; } 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" }, }); } }, STALE_WHILE_REVALIDATE: async ({ request, preloadResponsePromise, fallbackUrl, event, }) => { console.debug("[Service Worker][SWR] Fetching URL: ", event.request.url); // First try to get the resource from the cache const responseFromCache = await caches.match(request); const responseFromNetwork = new Promise(async (resolve) => { const responseFromPreload = await preloadResponsePromise; if (responseFromPreload) { event.waitUntil(putInCache(request, responseFromPreload.clone())); return resolve(responseFromPreload); } try { const response = await fetch(request); event.waitUntil(putInCache(request, response.clone())); return resolve(response); } catch { const fallbackResponse = await caches.match(fallbackUrl); if (fallbackResponse) { return resolve(fallbackResponse); } // when even the fallback response is not available, // there is nothing we can do, but we must always // return a Response object return resolve(new Response("Network error happened", { status: 408, headers: { "Content-Type": "text/plain" }, })); } }); return responseFromCache || responseFromNetwork; }, }; const selve = self; const wildcardize = (pattern) => { const regex = new RegExp(pattern .replace(/[.*+?^${}()|[\]\\]/g, "\\$&") .replace(/\\\?/g, ".") // `?` → match any single character .replace(/\\\*\\\*/g, ".*") // `**` → match anything (including `/`) .replace(/\\\*/g, "[^/]*") + // `*` → match anything except `/` "$"); return (text) => { return regex.test(text); }; }; const addResourcesToCache = async (resources) => { const cache = await caches.open(CACHE_NAME); await cache.addAll(resources); }; const putInCache = async (request, response) => { const cache = await caches.open(CACHE_NAME); await cache.put(request, response); }; const deleteCache = async (key) => { await caches.delete(key); }; const deleteOldCaches = async () => { const cacheKeepList = [CACHE_NAME]; const keyList = await caches.keys(); const cachesToDelete = keyList.filter((key) => !cacheKeepList.includes(key)); await Promise.all(cachesToDelete.map(deleteCache)); }; const enableNavigationPreload = async () => { if (selve.registration.navigationPreload) { await selve.registration.navigationPreload.enable(); } }; selve.addEventListener("install", (event) => { /* {{task.install}} */ console.debug(`[Service Worker] Installing tasks: /* {{task.install}} */ `); const resources = /* {{resourcesToCache}} */ []; console.debug(`[Service Worker] Installing resources: ${resources.length}/${resources.length}`); event.waitUntil(addResourcesToCache(resources)); }); selve.addEventListener("activate", (event) => { const task = /* {{task.activate}} */ Promise.resolve(); event.waitUntil(enableNavigationPreload()); event.waitUntil(deleteOldCaches()); event.waitUntil(task); console.debug(`[Service Worker] Activating tasks: enableNavigationPreload, deleteOldCaches, /* {{task.activate}} */ `); }); selve.addEventListener("fetch", (event) => { if (event.request.method !== "GET") { return; } const resources = /* {{resourcesToCache}} */ []; const cfURIS = /* {{strategy.cf}} */ []; if ([...resources, ...cfURIS].some((cfURI) => wildcardize(cfURI)(event.request.url))) { return event.respondWith(STRATEGY.CACHE_FIRST({ request: event.request, preloadResponsePromise: event.preloadResponse, fallbackUrl: "", event, })); } const nfURIs = /* {{strategy.nf}} */ []; if (nfURIs.some((nfURI) => wildcardize(nfURI)(event.request.url))) { return event.respondWith(STRATEGY.NETWORK_FIRST({ request: event.request, preloadResponsePromise: event.preloadResponse, fallbackUrl: "", event, })); } const swrURIs = /* {{strategy.swr}} */ []; if (swrURIs.some((swrURI) => wildcardize(swrURI)(event.request.url))) { return event.respondWith(STRATEGY.STALE_WHILE_REVALIDATE({ request: event.request, preloadResponsePromise: event.preloadResponse, fallbackUrl: "", event, })); } }); selve.addEventListener("push", function () { console.debug("[Service Worker] Pushing..."); });