Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Introducción a Workbox

8/16
Recursos

En esta clase vamos a ver como implementar service workers en nuestra aplicación.

Los service workers solo funcionan en producción.

Una recomendación siempre que trabajemos con service workers es ir a Clear Storage en la tab de Application de las DevTools, y limpiar la información del sitio. Esto desinstalara todo lo que es cache y limpiara los service workers.

Quienes habrán prestado atención a la documentación de create-react-app habrán leído que este incluye un service worker.
El service worker de Create React App hace algo llamado “SW Precache“, lo que hace es precargar y dejar disponibles offline todos los archivos necesarios para correr la aplicación. Una recomendación a la hora de hacer debugging es refrescar el sitio pues un service worker por lo general se inicializa después de la primera carga.

NUNCA conviene escribir nuestro propio service worker especialmente con herramientas de bajo nivel.

Para implementar nuestro propio service worker usaremos Workbox, una librería creada por Google para crear Service Workers.

Hay un pequeño detalle al momento de implementar Workbox en nuestro proyecto y es que estamos yendo en contra de los principios de Create React App y esto solo significa una cosa “eject”, esto nos llenaría de archivos que no nos sirven. Para evitar hacer eject vamos a instalar react-app-rewired y el plugin para webpack de workbox.

npm add workbox-webpack-plugin react-app-rewire-workbox react-app-rewired

Aportes 23

Preguntas 9

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Octubre 2020 para que funcione como lo indica el profesor hay instalar estas versiones

"react-app-rewire-workbox”: “2.0.1”,
“react-app-rewired”: “2.1.6”,
“workbox-webpack-plugin”: “4.3.1

El comando seria el siguiente:

npm add workbox-webpack-plugin@4.3.1 react-app[email protected] react-app[email protected] -E -D

De lo contrario nada funciona 😦 #CursoNecesitaUpdate

Aunque el proyecto esta desactualizado a nivel de dependencias, para que funcione deben copiar las versiones del package.json utilizadas en el curso

"workbox-webpack-plugin": "^3.3.1",
    "react-app-rewire-workbox": "^2.0.1",
    "react-app-rewired": "^1.5.2"

e instalar las dependencias de la forma

npm install --exact

Y funcionando hoy 2020/05/04 a pesar del versionamiento

nada de lo que esta en el curso funciona, tal cual es necesario actualizar, de hecho ni el codigo de ejemplo esta al 100 le faltan algunas dependencias que utilizan y no existen jeje,

Buenas!! no sé si alguno le pasó que cunado limpiaban el cache, refrescaban y ponían la aplicación offline chrome mostraba un error y no se veía la página.

Si veían la consola les mostraba el siguiente error

service-worker.js:11 Uncaught TypeError: workbox.precaching.suppressWarnings is not a function
    at service-worker.js:11

Error during service worker registration: TypeError: Failed to register a ServiceWorker: ServiceWorker script evaluation failed

Si da este problema cuando limpian el cache y como muestra el segundo error, no se registra el service worker por lo tanto no cachea nada.

Leyendo un poco lo que hace el método suppressWarnings es generar un log de precaching.

En la documentación de workbox https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.precaching ya no vi que estuviera ese método por lo tanto lo comenté de mi código en services-worker.js

/**
 * The workboxSW.precacheAndRoute() method efficiently caches and responds to
 * requests for URLs in the manifest.
 * See https://goo.gl/S9QRab
 */

// Precarga la app
self.__precacheManifest = [].concat(self.__precacheManifest || [])
//workbox.precaching.suppressWarnings()
workbox.precaching.precacheAndRoute(self.__precacheManifest, {})

a partir de ahí empezó a registrarme el cache sin problemas y cuando dejo la app offline, me muestra el header o lo cacheado en la home.

espero que sirva de algo.

Saludos.

Ya hace falta actualizar el curso, hay cosas que han cambiado, incluso otras no estan , y nos encontramos con problemas que lleva algo de tiempo solucionar

Al dia de hoy 26/10/2020 create-react-app no crea el serviceWorker por defecto, para eso tienes que hacerlo con este cli.

npx create-react-app my-app --template pwa

Luego en index, cambiar el

serviceWorkerRegistration.unregister();

por

serviceWorkerRegistration.register();

Hubiera preferido que en lugar de create-react-app se hiciera la app desde cero, en la vida real, los proyectos grandes eso es lo que hacen y aquí nos estamos amarrando mucho al boilerplate de CRA.

El curso y el profesor son muy buenos, lastima que esté tan desactualizado

Hola [email protected]… me salía el siguiente error al hacer build: Can’t find self.__WB_MANIFEST in your SW source.

se soluciona modificando el service-worker.js:
self.__precacheManifest = [].concat(self.__precacheManifest || [])
//workbox.precaching.suppressWarnings()
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)

Para quienes vean este curso, deben tomar en cuenta las siguientes notas debido a recientes actualizaciones.

  • Actualizar react-scripts en el proyecto ya que esta en la v1.1.4. ypara la fecha van por el 4.0.3

  • La API de themealDB ahora requiere un key (cuesta 2$ en su patreon)

  • NO USAR react-app-rewire, ya que esta esta desactualizada y casi deprecada, en su lugar usar craco es de muy facil y similar configuración

  • Ya no se ejecutan las estrategias como funciones, ahora son clases aqui dejo un ejemplo de como implementar una al registrar una ruta

// La API usa Stale While Revalidate para mayor velocidad
registerRoute(({url}) => 
  /^https?:\/\/www.themealdb.com\/api\/.*/,
  new StaleWhileRevalidate({
    cacheName: 'api',
  }), "GET"
)

y bonus aqui un ejemplo para interceptar los request tipo POST con background sync

const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
  maxRetentionTime: 24 * 60 // Retry for max of 24 Hours (specified in minutes)
});

registerRoute(({url}) => 
  /^https?:\/\/www.themealdb.com\/api\/.*/,
  new NetworkOnly({
    cacheName: 'api',
    plugins:[bgSyncPlugin]
  }), "POST"
)

PD: las nuevas versiones de CRA incluyen workbox y un template basico (service-worker.js) para el registro en cache del app shell cuando se registra el serviceworker, solo queda de parte uno agregar rutas adicionales (api, assets, etc…)

espero esto sea de ayuda para alguien en la comunidad.

Pase 2 horas creando mi service workers… -_- pero lo logre

Al dia de hoy 29/10/2021 create-react-app no crea el serviceWorker por defecto, para eso tienes que hacerlo con este cli.

npx create-react-app my-app --template pwa

Luego en index, cambiar el

serviceWorkerRegistration.unregister();

por

serviceWorkerRegistration.register();

el service-worker.js debe quedar así

/* eslint-disable no-restricted-globals */

// This service worker can be customized!
// See https://developers.google.com/web/tools/workbox/modules
// for the list of available Workbox modules, or add any other
// code you'd like.
// You can also remove this file if you'd prefer not to use a
// service worker, and the Workbox build step will be skipped.

import { clientsClaim } from 'workbox-core';
import { ExpirationPlugin } from 'workbox-expiration';
import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching';
import { registerRoute, NavigationRoute } from 'workbox-routing';
import { StaleWhileRevalidate, CacheFirst, NetworkFirst } from 'workbox-strategies';

clientsClaim();

// Precache all of the assets generated by your build process.
// Their URLs are injected into the manifest variable below.
// This variable must be present somewhere in your service worker file,
// even if you decide not to use precaching. See https://cra.link/PWA
precacheAndRoute(self.__WB_MANIFEST);

// Set up App Shell-style routing, so that all navigation requests
// are fulfilled with your index.html shell. Learn more at
// https://developers.google.com/web/fundamentals/architecture/app-shell
const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$');
registerRoute(
  // Return false to exempt requests from being fulfilled by index.html.
  ({ request, url }) => {
    // If this isn't a navigation, skip.
    if (request.mode !== 'navigate') {
      return false;
    } // If this is a URL that starts with /_, skip.

    if (url.pathname.startsWith('/_')) {
      return false;
    } // If this looks like a URL for a resource, because it contains // a file extension, skip.

    if (url.pathname.match(fileExtensionRegexp)) {
      return false;
    } // Return true to signal that we want to use the handler.

    return true;
  },
  createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html')
);

// An example runtime caching route for requests that aren't handled by the
// precache, in this case same-origin .png requests like those from in public/
registerRoute(
  // Add in any other file extensions or routing criteria as needed.
  ({ url }) => url.origin === self.location.origin && url.pathname.endsWith('.png'), // Customize this strategy as needed, e.g., by changing to CacheFirst.
  new StaleWhileRevalidate({
    cacheName: 'images',
    plugins: [
      // Ensure that once this runtime cache reaches a maximum size the
      // least-recently used images are removed.
      new ExpirationPlugin({ maxEntries: 50 }),
    ],
  })
);

registerRoute(
  // Add in any other file extensions or routing criteria as needed.
  ({ url }) => url.origin === self.location.origin && url.pathname.endsWith('.png'), // Customize this strategy as needed, e.g., by changing to CacheFirst.
  new StaleWhileRevalidate({
    cacheName: 'images',
    plugins: [
      // Ensure that once this runtime cache reaches a maximum size the
      // least-recently used images are removed.
      new ExpirationPlugin({ maxEntries: 50 }),
    ],
  })
);

// This allows the web app to trigger skipWaiting via
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

// Any other custom service worker logic can go here.

// App Shell
new NavigationRoute('/index.html')

// La API usa Stale While Revalidate para mayor velocidad
registerRoute(/^https?:\/\/www.themealdb.com\/api\/.*/, new StaleWhileRevalidate({}),
 'GET')

// Last fuentes van con Cache First y vencen al mes
registerRoute(/^https:\/\/fonts.(?:googleapis|gstatic).com\/(.*)/, 
  new CacheFirst({
    cacheName: 'google-fonts-cache',
    plugins: [
      new ExpirationPlugin({  maxAgeSeconds: 30 * 24 * 60 * 60 })
    ]
  }),
  'GET')

// Todo lo demás usa Network First
registerRoute(/^https?.*/,
  new NetworkFirst(), 'GET')

Si mi proyecto no es un CreateReactApp, no tengo la necesidad de crear el archivo config-overrides.js, cierto?

Específicamente, ¿Qué es lo que hace esta linea?:

self.__precacheManifest = [].concat(self.__precacheManifest || []) 

https://www.youtube.com/watch?v=LL9uD1M8p7U
como crear un custom service worker con create react app esta en ingles pero no se necesita saber ingles para saber que esta haciendo el bato r e c o m e n d a d o

???

> [email protected]0.1.0 build C:\Users\Usuario\Documents\prjs\react\platzi-pwa
> react-app-rewired build

Generating Service Worker
Creating an optimized production build...
Failed to compile.

Cannot read property 'make' of undefined

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected]0.1.0 build: `react-app-rewired build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected]0.1.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.```

¿Se podría hacer un custom environment de react y usar WorkBox, para evitar usar create-react-app?

al 19/11/20 para que funcione, tuve que instalar versiones anteriores a la fecha, el comando es así

<npm add workbox-webpack-plugin@4.3.1 react-app[email protected] react-app[email protected] -E -D>

y después comentar en service-worker.js

<//workbox.precaching.suppressWarnings()>

así pudo correr…!!!

Tengo el siguiente problema cuando actualizo “react-scripts” el cual la versión actual es vulnerable. https://nodesecurity.io/advisories/725
Y si lo actualizo, la web deja de funcionar.

npm WARN [email protected] requires a peer of [email protected]^1.0.14 but none is installed. You must install peer dependencies yourself.

A alguien mas le sucedio que no le aparecen los service-worker entre los archivos mostrados en Network?

Si alguno tiene problemas al hacer el build o porque no registra el service worker, instalen exactamente las mismas versiones de las dependencias!

"workbox-webpack-plugin": "^3.3.1",
"react-app-rewire-workbox": "^2.0.1",
"react-app-rewired": "^1.5.2"

m