enrutamiento de caja de trabajo

Un service worker puede interceptar solicitudes de red de una página. Puede responder a el navegador con contenido almacenado en caché, contenido de la red o contenido generado en el service worker.

workbox-routing es un módulo que facilita "enrutar" estas solicitudes a diferentes funciones que ofrecen respuestas.

Cómo se realiza el enrutamiento

Cuando una solicitud de red genera un evento de recuperación de service worker, workbox-routing intentará responder a la solicitud con las rutas y los controladores proporcionados.

Diagrama de enrutamiento de la caja de trabajo

Estos son los aspectos principales que debes tener en cuenta a partir de la información anterior:

  • El método de solicitud es importante. De forma predeterminada, las rutas se registran GET solicitudes. Si quieres interceptar otros tipos de solicitudes, necesitarás para especificar el método.

  • El orden del registro de rutas es importante. Si hay varias Rutas que puede manejar una solicitud, la ruta que se registra primero se usará para responder a la solicitud.

Existen varias formas de registrar una ruta: puedes usar devoluciones de llamada, llamadas regulares con expresiones regulares o instancias de Route.

Coincidencias y manejo en las rutas

Una "ruta" en la caja de trabajo no son más que dos funciones: una operación de “coincidencias” función para determinar si la ruta debe coincidir con una solicitud y un “control” la función, que debe manejar la solicitud y responder con una respuesta.

Workbox incluye algunos asistentes que realizan la coincidencia y el manejo de pero si alguna vez deseas tener un comportamiento diferente, escribir un la coincidencia personalizada y la función de controlador es la mejor opción.

R función de devolución de llamada coincidente se le pasa un ExtendableEvent: Request y un URL objeto que puedes de coincidencia mostrando un valor verdadero. Para un ejemplo sencillo, podrías comparar una URL específica, como esta:

const matchCb = ({url, request, event}) => {
  return url.pathname === '/special/url';
};

La mayoría de los casos de uso se pueden cubrir examinando o probando url o request

R función de devolución de llamada del controlador recibirán la misma ExtendableEvent: Request y URL objeto junto con un valor params, que es el valor que devuelve el comando "match" .

const handlerCb = async ({url, request, event, params}) => {
  const response = await fetch(request);
  const responseBody = await response.text();
  return new Response(`${responseBody} <!-- Look Ma. Added Content. -->`, {
    headers: response.headers,
  });
};

El controlador debe mostrar una promesa que se resuelva en Response. En este ejemplo, usamos async y await. De forma interna, el valor de Response que se muestra se unirá en una promesa.

Puedes registrar estas devoluciones de llamada de la siguiente manera:

import {registerRoute} from 'workbox-routing';

registerRoute(matchCb, handlerCb);

La única limitación es que la columna "match" la devolución de llamada debería de forma síncrona mostrar un mensaje verdadero no puedes realizar ningún trabajo asíncrono. Esto se debe a que Router debe responder de forma síncrona al evento de recuperación o permitir que a otros eventos de recuperación.

Normalmente, el "controlador" la devolución de llamada usará una de las estrategias proporcionadas mediante workbox-strategies, como se muestra aquí:

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

registerRoute(matchCb, new StaleWhileRevalidate());

En esta página, nos centraremos en workbox-routing, pero puedes Obtén más información sobre estas estrategias en las cajas de trabajo.

Cómo registrar una ruta de expresiones regulares

Una práctica común es usar una expresión regular en lugar de una “coincidencia” devolución de llamada. Workbox hace que esto sea fácil de implementar de la siguiente manera:

import {registerRoute} from 'workbox-routing';

registerRoute(new RegExp('/styles/.*\\.css'), handlerCb);

Para las solicitudes del mismo origen, esta expresión regular coincidirá, siempre y cuando la URL de la solicitud coincida expresión regular.

  • https://example.com/styles/main.css
  • https://example.com/styles/nested/file.css
  • https://example.com/nested/styles/directory.css

Sin embargo, para las solicitudes de origen cruzado, las expresiones regulares debe coincidir con el comienzo de la URL. Esto se debe a que poco probable que con una expresión regular new RegExp('/styles/.*\\.css') buscaste hacer coincidir los archivos CSS de terceros.

  • https://cdn.third-party-site.com/styles/main.css
  • https://cdn.third-party-site.com/styles/nested/file.css
  • https://cdn.third-party-site.com/nested/styles/directory.css

Si deseas este comportamiento, solo debes asegurarte de que la frecuencia coincide con el principio de la URL. Si quisiéramos hacer coincidir el solicitudes para https://cdn.third-party-site.com, podríamos usar el la expresión new RegExp('https://cdn\\.third-party-site\\.com.*/styles/.*\\.css').

  • https://cdn.third-party-site.com/styles/main.css
  • https://cdn.third-party-site.com/styles/nested/file.css
  • https://cdn.third-party-site.com/nested/styles/directory.css

Si deseas buscar coincidencias, tanto locales como de terceros, puedes usar un comodín al comienzo de la expresión regular, pero debes hacerlo con precaución para asegurarte de que no cause comportamientos inesperados en tu aplicación web.

Cómo registrar una ruta de navegación

Si tu sitio tiene una aplicación de una sola página, puedes utilizar una NavigationRoute a devolver una respuesta específica para todos de navegación.

import {createHandlerBoundToURL} from 'workbox-precaching';
import {NavigationRoute, registerRoute} from 'workbox-routing';

// This assumes /app-shell.html has been precached.
const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler);
registerRoute(navigationRoute);

Cada vez que un usuario visite tu sitio en el navegador, se generará la solicitud de la página Debe ser una solicitud de navegación y se entregará la página almacenada en caché /app-shell.html. (Nota: La página debe estar almacenada en caché a través de workbox-precaching o mediante tu tu propio paso de instalación).

De forma predeterminada, esto responderá a todas las solicitudes de navegación. Si deseas restringirlo para que responda a un subconjunto de URLs, puedes usar el allowlist y denylist opciones para restringir qué páginas coincidirán con esta ruta.

import {createHandlerBoundToURL} from 'workbox-precaching';
import {NavigationRoute, registerRoute} from 'workbox-routing';

// This assumes /app-shell.html has been precached.
const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler, {
  allowlist: [new RegExp('/blog/')],
  denylist: [new RegExp('/blog/restricted/')],
});
registerRoute(navigationRoute);

Lo único que debes tener en cuenta es que denylist ganará si una URL está en ambos allowlist y denylist.

Configura un controlador predeterminado

Si quieres proporcionar un "controlador" para solicitudes que no coinciden con una ruta, puede establecer un controlador predeterminado.

import {setDefaultHandler} from 'workbox-routing';

setDefaultHandler(({url, event, params}) => {
  // ...
});

Configura un controlador de captura

En caso de que alguna de tus rutas arroje un error, puedes capturar y se degradan de forma elegante mediante la configuración de un controlador catch.

import {setCatchHandler} from 'workbox-routing';

setCatchHandler(({url, event, params}) => {
  ...
});

Cómo definir una ruta para solicitudes que no son GET

De forma predeterminada, se supone que todas las rutas corresponden a solicitudes GET.

Si quieres enrutar otras solicitudes, como una POST, necesitas para definir el método al registrar la ruta, de la siguiente manera:

import {registerRoute} from 'workbox-routing';

registerRoute(matchCb, handlerCb, 'POST');
registerRoute(new RegExp('/api/.*\\.json'), handlerCb, 'POST');

Registro del router

Deberías poder determinar el flujo de una solicitud con los registros de workbox-routing, que destacará las URLs que se están procesando a través de Workbox.

Registros de enrutamiento

Si necesitas información más detallada, puedes establecer el nivel de registro en debug para Ver registros en solicitudes que no maneja el router. Consulta nuestra guía de depuración para obtener más información configurar el nivel de registro.

Mensajes de depuración y enrutamiento de registros

Uso avanzado

Si quieres tener más control sobre cuándo se proporciona el router de la caja de trabajo solicitudes, puedes crear tu propia Instancia Router y llamada Es handleRequest() cada vez que quieras usar el router para responder a una solicitud.

import {Router} from 'workbox-routing';

const router = new Router();

self.addEventListener('fetch', event => {
  const {request} = event;
  const responsePromise = router.handleRequest({
    event,
    request,
  });
  if (responsePromise) {
    // Router found a route to handle the request.
    event.respondWith(responsePromise);
  } else {
    // No route was found to handle the request.
  }
});

Cuando uses Router directamente, también deberás usar la clase Route, o cualquiera de las clases extendidas para registrar rutas.

import {Route, RegExpRoute, NavigationRoute, Router} from 'workbox-routing';

const router = new Router();
router.registerRoute(new Route(matchCb, handlerCb));
router.registerRoute(new RegExpRoute(new RegExp(...), handlerCb));
router.registerRoute(new NavigationRoute(handlerCb));

Tipos

NavigationRoute

NavigationRoute facilita la creación de un workbox-routing.Route que coincide con el navegador [solicitudes de navegación]https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading#first_what_are_navigation_requests.

Solo coincidirá con las solicitudes entrantes que https://fetch.spec.whatwg.org/#concept-request-mode|mode se estableció en navigate.

De manera opcional, solo puedes aplicar esta ruta a un subconjunto de solicitudes de navegación Mediante uno o ambos parámetros denylist y allowlist.

Propiedades

  • constructor

    void

    Si se proporcionan denylist y allowlist, denylist tendrá prioridad y la solicitud no coincidirá con esta ruta.

    Las expresiones regulares en allowlist y denylist se comparan con los atributos [pathname]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname y [search]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search partes de la URL solicitada.

    Nota: Estas regex pueden evaluarse en función de cada URL de destino durante la navegación. Evita el uso RegExps complejos, De lo contrario, es posible que los usuarios experimenten demoras cuando naveguen por tu sitio.

    La función constructor se ve de la siguiente manera:

    (handler: RouteHandler, options?: NavigationRouteMatchOptions) => {...}

  • catchHandler
  • coincidencia
  • method

    HTTPMethod

  • setCatchHandler

    void

    La función setCatchHandler se ve de la siguiente manera:

    (handler: RouteHandler) => {...}

    • handler

      Una devolución de llamada función que devuelve una promesa que da como resultado una respuesta

NavigationRouteMatchOptions

Propiedades

  • lista de anunciantes permitidos

    ExpExp[] opcional

  • lista de bloqueo

    ExpExp[] opcional

RegExpRoute

RegExpRoute facilita la creación de una expresión regular basada workbox-routing.Route

En el caso de las solicitudes del mismo origen, la regex solo debe coincidir con una parte de la URL. Para solicitudes contra servidores de terceros, debes definir una regex que coincida el inicio de la URL.

Propiedades

  • constructor

    void

    Si la expresión regular contiene [grupos de captura]https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references, los valores capturados se pasan al params de workbox-routing~handlerCallback argumento.

    La función constructor se ve de la siguiente manera:

    (regExp: RegExp, handler: RouteHandler, method?: HTTPMethod) => {...}

    • regExp

      RegExp

      La expresión regular que debe coincidir con las URLs.

    • handler

      Una devolución de llamada que devuelve una promesa, que da como resultado una respuesta.

    • method

      HTTPMethod opcional

  • catchHandler
  • coincidencia
  • method

    HTTPMethod

  • setCatchHandler

    void

    La función setCatchHandler se ve de la siguiente manera:

    (handler: RouteHandler) => {...}

    • handler

      Una devolución de llamada función que devuelve una promesa que da como resultado una respuesta

Route

Un Route consiste en un par de funciones de devolución de llamada "match" y "handler". La coincidencia la devolución de llamada determina si una ruta se debe usar para "manejar" pañal solicitud mostrando un valor no falso, si es posible. El "controlador" devolución de llamada Se llama cuando hay una coincidencia y se debe mostrar una promesa que resuelva el problema. a un Response.

Propiedades

  • constructor

    void

    Constructor de la clase Route.

    La función constructor se ve de la siguiente manera:

    (match: RouteMatchCallback, handler: RouteHandler, method?: HTTPMethod) => {...}

    • coincidencia

      Una función de devolución de llamada que determina si la ruta coincide con un determinado fetch si muestra un valor no falso.

    • handler

      Una devolución de llamada función que devuelve una promesa que da como resultado una respuesta.

    • method

      HTTPMethod opcional

  • catchHandler
  • coincidencia
  • method

    HTTPMethod

  • setCatchHandler

    void

    La función setCatchHandler se ve de la siguiente manera:

    (handler: RouteHandler) => {...}

    • handler

      Una devolución de llamada función que devuelve una promesa que da como resultado una respuesta

Router

Se puede usar el router para procesar un FetchEvent con uno o más workbox-routing.Route, y se responde con un Response si existe una ruta coincidente.

Si ninguna ruta coincide con una solicitud determinada, el router usará una conexión si hay uno definido.

Si la ruta coincidente arroja un error, el router usará una sentencia “catch”. si uno está definido para tratar los problemas correctamente y responder con un Solicitud.

Si una solicitud coincide con varias rutas, la ruta registrada más antigua usarse para responder a la solicitud.

Propiedades

  • constructor

    void

    Inicializa un router nuevo.

    La función constructor se ve de la siguiente manera:

    () => {...}

  • rutas

    Map&lt;HTTPMethodRoute[]&gt;

  • addCacheListener

    void

    Agrega un objeto de escucha de eventos de mensaje para que las URLs se almacenen en caché desde la ventana. Esto es útil para almacenar en caché los recursos cargados en la página antes del momento en que el service worker empezó a controlarlo.

    El formato de los datos del mensaje que se envían desde la ventana debe ser el siguiente. En el que el array urlsToCache puede constar de cadenas de URL o un array de String de URL + objeto requestInit (la misma que pasarías a fetch())

    {
      type: 'CACHE_URLS',
      payload: {
        urlsToCache: [
          './script1.js',
          './script2.js',
          ['./script3.js', {mode: 'no-cors'}],
        ],
      },
    }
    

    La función addCacheListener se ve de la siguiente manera:

    () => {...}

  • addFetchListener

    void

    Agrega un objeto de escucha de eventos de recuperación para responder a eventos cuando coincide una ruta. la solicitud del evento.

    La función addFetchListener se ve de la siguiente manera:

    () => {...}

  • findMatchingRoute

    void

    Compara una solicitud y una URL (y opcionalmente un evento) con la lista de rutas registradas y, si hay una coincidencia, devuelve el resultado junto con cualquier parámetro que genere la coincidencia.

    La función findMatchingRoute se ve de la siguiente manera:

    (options: RouteMatchCallbackOptions) => {...}

    • muestra

      objeto

      Un objeto con propiedades route y params Se propagan si se encuentra una ruta coincidente o undefined de lo contrario.

  • handleRequest

    void

    Aplicar las reglas de enrutamiento a un objeto FetchEvent para obtener una respuesta de un al controlador de rutas adecuado.

    La función handleRequest se ve de la siguiente manera:

    (options: object) => {...}

    • opciones

      objeto

      • evento

        ExtendableEvent

        El evento que activó el para cada solicitud.

      • request

        Solicitud

        La solicitud que se debe controlar.

    • muestra

      Promise&lt;Response&gt;

      Se devuelve una promesa si un la ruta registrada puede manejar la solicitud. Si no hay coincidencias ruta y no hay defaultHandler, se devuelve undefined.

  • registerRoute

    void

    Registra una ruta con el router.

    La función registerRoute se ve de la siguiente manera:

    (route: Route) => {...}

    • ruta

      La ruta que se registrará.

  • setCatchHandler

    void

    Si una ruta arroja un error mientras se procesa una solicitud, esta handler se llamará y tendrá la oportunidad de proporcionar una respuesta.

    La función setCatchHandler se ve de la siguiente manera:

    (handler: RouteHandler) => {...}

    • handler

      Una devolución de llamada que devuelve una promesa, que da como resultado una respuesta.

  • setDefaultHandler

    void

    Define un handler predeterminado que se llame cuando no hay rutas de forma explícita. coincide con la solicitud entrante.

    Cada método HTTP ("GET", "POST", etc.) obtiene su propio controlador predeterminado.

    Sin un controlador predeterminado, las solicitudes no coincidentes irán en contra del red como si no hubiera un service worker presente.

    La función setDefaultHandler se ve de la siguiente manera:

    (handler: RouteHandler, method?: HTTPMethod) => {...}

    • handler

      Una devolución de llamada que devuelve una promesa, que da como resultado una respuesta.

    • method

      HTTPMethod opcional

  • unregisterRoute

    void

    Cancela el registro de una ruta con el router.

    La función unregisterRoute se ve de la siguiente manera:

    (route: Route) => {...}

    • ruta

      La ruta para cancelar el registro.

Métodos

registerRoute()

workbox-routing.registerRoute(
  capture: string | RegExp | RouteMatchCallback | Route,
  handler?: RouteHandler,
  method?: HTTPMethod,
)

Registra fácilmente una regex, una cadena o una función con un almacenamiento en caché estrategia a una instancia de un router singleton.

Este método generará una Ruta para ti si es necesario y llama a workbox-routing.Router#registerRoute.

Parámetros

  • capturar

    string | Exp. | RouteMatchCallback | Ruta

    Si el parámetro de captura es Route, se ignorarán todos los demás argumentos.

  • handler

    RouteHandler opcional

  • method

    HTTPMethod opcional

Muestra

  • El Route generado.

setCatchHandler()

workbox-routing.setCatchHandler(
  handler: RouteHandler,
)

Si una ruta arroja un error mientras se procesa una solicitud, esta handler se llamará y tendrá la oportunidad de proporcionar una respuesta.

Parámetros

  • handler

    Una devolución de llamada que devuelve una promesa, que da como resultado una respuesta.

setDefaultHandler()

workbox-routing.setDefaultHandler(
  handler: RouteHandler,
)

Define un handler predeterminado que se llame cuando no hay rutas de forma explícita. coincide con la solicitud entrante.

Sin un controlador predeterminado, las solicitudes no coincidentes irán en contra del red como si no hubiera un service worker presente.

Parámetros

  • handler

    Una devolución de llamada que devuelve una promesa, que da como resultado una respuesta.