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.
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.
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.
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
-
void
Si se proporcionan
denylist
yallowlist
,denylist
tendrá prioridad y la solicitud no coincidirá con esta ruta.Las expresiones regulares en
allowlist
ydenylist
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) => {...}
-
Una devolución de llamada que devuelve una promesa, que da como resultado una respuesta.
-
NavigationRouteMatchOptions opcional
-
-
RouteHandlerObject opcional
-
HTTPMethod
-
void
La función
setCatchHandler
se ve de la siguiente manera:(handler: RouteHandler) => {...}
-
Una devolución de llamada función que devuelve una promesa que da como resultado una respuesta
-
NavigationRouteMatchOptions
Propiedades
-
ExpExp[] opcional
-
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 alparams
deworkbox-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
- muestra
-
- catchHandler
RouteHandlerObject opcional
- handler
- 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
- muestra
-
- catchHandler
RouteHandlerObject opcional
- handler
- 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:() => {...}
- muestra
-
- rutas
Map<HTTPMethodRoute[]>
- 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 + objetorequestInit
(la misma que pasarías afetch()
){ 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) => {...}
- opciones
- muestra
objeto
Un objeto con propiedades
route
yparams
Se propagan si se encuentra una ruta coincidente oundefined
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<Response>
Se devuelve una promesa si un la ruta registrada puede manejar la solicitud. Si no hay coincidencias ruta y no hay
defaultHandler
, se devuelveundefined
.
-
- 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,
): Route
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,
): void
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,
): void
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.