Last active
April 9, 2022 22:47
-
-
Save gugadev/b2dfa3f2cec761069af7a67026a78817 to your computer and use it in GitHub Desktop.
Revisions
-
gugadev revised this gist
Apr 9, 2022 . 2 changed files with 13 additions and 10 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -134,11 +134,11 @@ if ("function" === typeof importScripts) { if (event.request.url.includes("aec-notifications")) return; if (event.request.url.includes("chrome-extension")) return; try { event.respondWith(fetchHandler(event)); } catch (err) { console.warn(`Falló la petición a "${event.request.url}:"`, err); } }); // Offline Google Analytics (if you want it) This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -7,12 +7,14 @@ import { registerRoute, NavigationRoute } from "workbox-routing"; import { CacheFirst, StaleWhileRevalidate } from "workbox-strategies"; import { CacheableResponsePlugin } from "workbox-cacheable-response"; import { RangeRequestsPlugin } from "workbox-range-requests"; import { initialize as initializeGA } from "workbox-google-analytics"; declare const self: ServiceWorkerGlobalScope; if (self && self.location && self.location.hostname === "localhost") { console.log("Localhost detected. Running Workbox in debug mode!"); // ? No se puede establecer el modo de bug así :p //workbox.setConfig({ debug: true }); } // limpiamos el caché viejo @@ -107,6 +109,7 @@ registerRoute( ); /** * ! Importante * Este método almacena en caché las peticiones ajax que se hagan. */ const fetchHandler = async (event: FetchEvent) => { @@ -135,12 +138,12 @@ self.addEventListener("fetch", (event: FetchEvent) => { if (event.request.url.includes("aec-notifications")) return; if (event.request.url.includes("chrome-extension")) return; try { event.respondWith(fetchHandler(event)); } catch (err) { console.warn(`Falló la petición a "${event.request.url}:"`, err); } }); // Offline Google Analytics (opcional) initializeGA(); -
gugadev created this gist
Apr 9, 2022 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,29 @@ /** * * This is not in use. * * Para conocimiento general: * Esta es una forma de generar el "precache manifest" * de un service worker. La otra forma es como se detalla * en el script de NPM "sw" en el presente package.json. */ const workboxBuild = require("workbox-build"); const buildServiceWorker = () => { return workboxBuild .injectManifest({ swSrc: "src/sw.js", // service worker personalizado swDest: "dist/sw.js", // service worker generado por Workbox. globDirectory: "dist", globPatterns: ["**/*.{js,css,html,png,svg}"], maximumFileSizeToCacheInBytes: 5 * 1024 * 1024, // 5mb globIgnores: ["**/*.map", "**/asset-manifest*.js", "**/sw.js"] }) .then(({ count, size, warnings }) => { warnings.forEach(console.warn); console.info(`${count} archivos serán precacheados. Total: ${size / (1024 * 1024)} MBs.`); }) .catch(err => { console.warn(`Error al inyectar service worker: ${err}`); }); }; buildServiceWorker(); This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,9 @@ { "scripts": { "build": "<your framework script here> && npm run sw", "build-sw": "node scripts/sw-build.js", "compile-sw": "esbuild --outfile=src/sw.js --bundle src/sw.ts", "inject-sw": "workbox injectManifest workbox-config.js", "sw": "npm run compile-sw && npm run inject-sw" } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,139 @@ /** * ! Importante * * Este archivo se encarga de registrar / suprimir * * el service worker presente. */ const isLocalhost = Boolean( window.location.hostname === "localhost" || // [::1] is the IPv6 localhost address. window.location.hostname === "[::1]" || // 127.0.0.0/8 are considered localhost for IPv4. window.location.hostname.match( /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ ) ); type Config = { onSuccess?: (registration: ServiceWorkerRegistration) => void; onUpdate?: (registration: ServiceWorkerRegistration) => void; }; export function register(env: Record<string, any>, config?: Config): void { if ("serviceWorker" in navigator) { // No debe funcionar en otro dominio que el que definamos en la property const publicUrl = new URL(env.VITE_APP_URL!, window.location.href); if (publicUrl.origin !== window.location.origin) { return; } window.addEventListener("load", () => { const swUrl = `${window.location.origin}/sw.js`; if (isLocalhost) { // This is running on localhost. Let's check if a service worker still exists or not. checkValidServiceWorker(swUrl, config); // Add some additional logging to localhost, pointing developers to the // service worker/PWA documentation. navigator.serviceWorker.ready.then(() => { console.log( "This web app is being served cache-first by a service " + "worker." ); }); } else { // Is not localhost. Just register service worker registerValidSW(swUrl, config); } }); } } export function unregister(): void { if ("serviceWorker" in navigator) { navigator.serviceWorker.ready .then((registration) => { registration.unregister(); }) .catch((error) => { console.error(error.message); }); } } function registerValidSW(swUrl: string, config?: Config) { navigator.serviceWorker .register(swUrl) .then((registration) => { registration.onupdatefound = () => { const installingWorker = registration.installing; if (installingWorker == null) { return; } installingWorker.onstatechange = () => { if (installingWorker.state === "installed") { if (navigator.serviceWorker.controller) { // At this point, the updated precached content has been fetched, // but the previous service worker will still serve the older // content until all client tabs are closed. console.log( "New content is available and will be used when all " + "tabs for this page are closed. See https://cra.link/PWA." ); // Execute callback if (config && config.onUpdate) { config.onUpdate(registration); } } else { // At this point, everything has been precached. // It's the perfect time to display a // "Content is cached for offline use." message. console.log("Content is cached for offline use."); // Execute callback if (config && config.onSuccess) { config.onSuccess(registration); } } } }; }; }) .catch((error) => { console.error("Error during service worker registration:", error); }); } function checkValidServiceWorker(swUrl: string, config?: Config) { // Check if the service worker can be found. If it can't reload the page. fetch(swUrl, { headers: { "Service-Worker": "script" }, }) .then((response) => { // Ensure service worker exists, and that we really are getting a JS file. const contentType = response.headers.get("content-type"); if ( response.status === 404 || (contentType != null && contentType.indexOf("javascript") === -1) ) { // No service worker found. Probably a different app. Reload the page. navigator.serviceWorker.ready.then((registration) => { registration.unregister().then(() => { window.location.reload(); }); }); } else { // Service worker found. Proceed as normal. registerValidSW(swUrl, config); } }) .catch(() => { console.log( "No internet connection found. App is running in offline mode." ); }); } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,151 @@ if ("function" === typeof importScripts) { importScripts( "https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js" ); // Workbox loaded if (workbox) { if (self && self.location && self.location.hostname === "localhost") { console.log("Localhost detected. Running Workbox in debug mode!"); workbox.setConfig({ debug: true }); } const { registerRoute, NavigationRoute } = workbox.routing; const { CacheFirst, StaleWhileRevalidate } = workbox.strategies; const { CacheableResponsePlugin } = workbox.cacheableResponse; const { RangeRequestsPlugin } = workbox.rangeRequests; const { cleanupOutdatedCaches, precacheAndRoute, createHandlerBoundToURL, } = workbox.precaching; // limpiamos el caché viejo cleanupOutdatedCaches() // Manifest injection point precacheAndRoute(self.__WB_MANIFEST); /** * Aquí empieza nuestra configuración **/ /** * ! Fallback a /index.html, ya que es una SPA, * ! pero para los casos de 2020 y 2021, * ! no hacemos efectivo este fallback **/ const indexRoute = new NavigationRoute(createHandlerBoundToURL("/index.html"), { denylist: [ /^\/__/, /\/[^\/]+.[^\/]+$/, new RegExp("/2020/"), new RegExp("/2021/") ], }); registerRoute(indexRoute); registerRoute( ({ request }) => request.destination === "image", new StaleWhileRevalidate({ cacheName: "aec-images", plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); registerRoute( ({ request }) => request.destination === "font", new StaleWhileRevalidate({ cacheName: "aec-fonts", plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); registerRoute( ({ request }) => request.destination === "style", new StaleWhileRevalidate({ cacheName: "aec-styles", plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); registerRoute( ({request}) => { const {destination} = request; return destination === 'video' || destination === 'audio' }, new CacheFirst({ cacheName: 'aec-multimedia', plugins: [ new CacheableResponsePlugin({ statuses: [200] }), new RangeRequestsPlugin(), ], }), ); /** * ! Importante * Para los casos de 2020 y 2021, los estáticos (incluyendo HTML) * son obtenidos de caché, pero por detrás hacen la petición para * actualizar los archivos desde la red. */ registerRoute( ({ url }) => url.pathname.startsWith("/2020"), new StaleWhileRevalidate({ plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); registerRoute( ({ url }) => url.pathname.startsWith("/2021"), new StaleWhileRevalidate({ plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); /** * ! Importante * Este método almacena en caché las peticiones ajax que se hagan. */ const fetchHandler = async (event) => { const cache = await caches.open("aec-api-v4"); const cachedResponse = await cache.match(event.request); if (cachedResponse) { // si está en caché, refrescamos el valor event.waitUntil(cache.add(event.request)); // y devolvemos lo que está en caché return cachedResponse; } // Si no encontramos una coincidencia en el caché, usa la red. return fetch(event.request).then((response) => { // para evitar errore de tipo "Failed to add/put" if (response.status === 200) { cache.put(event.request, response.clone()); } return response; }); } self.addEventListener("fetch", (event) => { if (event.request.method !== "GET") return; if (event.request.url.includes("aec-notifications")) return; if (event.request.url.includes("chrome-extension")) return; fetchHandler(event).then((response) => { event.respondWith(response); }).catch(err => { console.warn(`Falló la petición a "${event.request.url}:"`, err); }); }); // Offline Google Analytics (if you want it) workbox.googleAnalytics.initialize(); // You can fit other workbox modules and configure them how you want... } else { console.error(" Workbox could not be loaded. No offline support."); } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,146 @@ import { cleanupOutdatedCaches, precacheAndRoute, createHandlerBoundToURL, } from "workbox-precaching"; import { registerRoute, NavigationRoute } from "workbox-routing"; import { CacheFirst, StaleWhileRevalidate } from "workbox-strategies"; import { CacheableResponsePlugin } from "workbox-cacheable-response"; import { RangeRequestsPlugin } from "workbox-range-requests"; declare const self: ServiceWorkerGlobalScope; if (self && self.location && self.location.hostname === "localhost") { console.log("Localhost detected. Running Workbox in debug mode!"); workbox.setConfig({ debug: true }); } // limpiamos el caché viejo cleanupOutdatedCaches() // Aquí se inyectan las rutas que genera Workbox precacheAndRoute(self.__WB_MANIFEST); /** * ! Importante * Fallback a /index.html, ya que es una SPA, * pero para los casos de 2020 y 2021, * no hacemos efectivo este fallback **/ const indexRoute = new NavigationRoute(createHandlerBoundToURL("/index.html"), { denylist: [ /^\/__/, /\/[^\/]+.[^\/]+$/, new RegExp("/2020/"), new RegExp("/2021/") ], }); registerRoute(indexRoute); registerRoute( ({ request }) => request.destination === "image", new StaleWhileRevalidate({ cacheName: "aec-images", plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); registerRoute( ({ request }) => request.destination === "font", new StaleWhileRevalidate({ cacheName: "aec-fonts", plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); registerRoute( ({ request }) => request.destination === "style", new StaleWhileRevalidate({ cacheName: "aec-styles", plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); registerRoute( ({request}) => { const {destination} = request; return destination === 'video' || destination === 'audio' }, new CacheFirst({ cacheName: 'aec-multimedia', plugins: [ new CacheableResponsePlugin({ statuses: [200] }), new RangeRequestsPlugin(), ], }), ); registerRoute( ({ url }) => url.origin === self.location.origin && url.pathname.endsWith(".json"), new CacheFirst({ cacheName: "data", plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); /** * ! Importante * Para los casos de 2020 y 2021, los estáticos (incluyendo HTML) * son obtenidos de caché, pero por detrás hacen la petición para * actualizar los archivos desde la red. */ registerRoute( ({ url }) => url.pathname.startsWith("/2020"), new StaleWhileRevalidate({ plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); registerRoute( ({ url }) => url.pathname.startsWith("/2021"), new StaleWhileRevalidate({ plugins: [new CacheableResponsePlugin({ statuses: [0, 200] })], }) ); /** * Este método almacena en caché las peticiones ajax que se hagan. */ const fetchHandler = async (event: FetchEvent) => { const cache = await caches.open("aec-api-v4"); const cachedResponse = await cache.match(event.request); if (cachedResponse) { // si está en caché, refrescamos el valor event.waitUntil(cache.add(event.request)); // y devolvemos lo que está en caché return cachedResponse; } // Si no encontramos una coincidencia en el caché, usa la red. return fetch(event.request).then((response) => { // para evitar errore de tipo "Failed to add/put" if (response.status === 200) { cache.put(event.request, response.clone()); } return response; }); } self.addEventListener("fetch", (event: FetchEvent) => { if (event.request.method !== "GET") return; if (event.request.url.includes("aec-notifications")) return; if (event.request.url.includes("chrome-extension")) return; fetchHandler(event).then((response) => { event.respondWith(response); }).catch(err => { console.warn(`Falló la petición a "${event.request.url}:"`, err); }); }); // Offline Google Analytics (opcional) workbox.googleAnalytics.initialize(); This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,8 @@ module.exports = { swSrc: "src/sw.js", swDest: "dist/sw.js", // o build, depende de cómo se llame el folder de compilación globDirectory: "dist", // o build, depende de cómo se llame el folder de compilación globPatterns: ["**/*.{js,css,html,png,svg}"], maximumFileSizeToCacheInBytes: 5 * 1024 * 1024, // 5mb globIgnores: ["**/*.map", "**/asset-manifest*.js", "**/sw.js"], };