Um service worker pode interceptar solicitações de rede para uma página. Ele pode responder a o navegador com conteúdo armazenado em cache, conteúdo da rede ou conteúdo gerado no service worker.
O workbox-routing
é um módulo que facilita o "roteamento" essas solicitações
diferentes funções que fornecem respostas.
Como o roteamento é realizado
Quando uma solicitação de rede causa um evento de busca de um service worker, workbox-routing
tentará responder à solicitação usando as rotas e os manipuladores fornecidos.
Os principais pontos a serem observados acima são:
O método de uma solicitação é importante. Por padrão, as rotas são registradas para
GET
. Para interceptar outros tipos de solicitações, você vai precisar para especificar o método.A ordem do registro da rota é importante. Se vários trajetos forem registrada para processar uma solicitação, a rota registrada primeiro será usado para responder à solicitação.
Há algumas maneiras de registrar uma rota: você pode usar callbacks, funções ou instâncias de rota.
Correspondência e manipulação em rotas
Uma "rota" na caixa de trabalho não é mais do que duas funções: uma "correspondência" função para determinar se a rota deve corresponder a uma solicitação e a um "processamento" função, que deve processar a solicitação e responder com uma resposta.
A caixa de trabalho vem com alguns auxiliares que realizam a correspondência e o processamento de mas, se quiser um comportamento diferente, escrever uma a função de gerenciador e correspondência personalizada é a melhor opção.
Um
função de callback correspondente
recebe um
ExtendableEvent
,
Request
e um
URL
objeto que você pode
correspondentes, retornando um valor verdadeiro. Para um exemplo simples, você pode corresponder com
um URL específico, como:
const matchCb = ({url, request, event}) => {
return url.pathname === '/special/url';
};
A maioria dos casos de uso pode ser abordada examinando / testando a url
ou as
request
.
Um
função de callback do gerenciador
recebem o mesmo
ExtendableEvent
,
Request
URL
objeto junto com
um valor params
, que é o valor retornado pelo método "match" função.
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,
});
};
Seu gerenciador precisa retornar uma promessa que seja resolvida como Response
. Neste
exemplo, estamos usando
async
e await
.
Internamente, o valor de retorno Response
será encapsulado em uma promessa.
Você pode registrar esses callbacks da seguinte forma:
import {registerRoute} from 'workbox-routing';
registerRoute(matchCb, handlerCb);
A única limitação é que a "correspondência" callback deve retornar de forma síncrona um verdadeiro
não será possível realizar nenhum trabalho assíncrono. A razão para isso é que,
o Router
precisa responder de forma síncrona ao evento de busca ou permitir a queda
outros eventos de busca.
Normalmente, o "manipulador" callback usaria uma das estratégias fornecidas por estratégias de caixa de trabalho, como:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
registerRoute(matchCb, new StaleWhileRevalidate());
Nesta página, vamos nos concentrar em workbox-routing
, mas você pode
Saiba mais sobre essas estratégias em estratégias de caixa de trabalho.
Como registrar uma rota de expressão regular
Uma prática comum é usar uma expressão regular em vez de uma "correspondência" o retorno de chamada. O Workbox facilita a implementação dessa forma:
import {registerRoute} from 'workbox-routing';
registerRoute(new RegExp('/styles/.*\\.css'), handlerCb);
Para solicitações do mesma origem, esta expressão regular corresponderá, desde que o URL da solicitação corresponda ao expressão regular.
- https://example.com/styles/main.css
- https://example.com/styles/nested/file.css
- https://example.com/nested/styles/directory.css
No entanto, para solicitações de origem cruzada, as expressões regulares
deve corresponder ao início do URL. A razão para isso é que
é improvável que, com uma expressão regular new RegExp('/styles/.*\\.css')
você pretendia corresponder
a arquivos CSS de terceiros.
- 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
Se você quis esse comportamento, só precisa garantir que a imagem
expressão corresponde ao início do URL. Se quisermos corresponder
para https://cdn.third-party-site.com
, poderíamos usar a solicitação
expressão 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
Se você quiser fazer a correspondência de empresas locais e de terceiros, use um caractere curinga no início da expressão regular, mas isso deve ser feito com cautela para garantir que ele não cause comportamentos inesperados no seu aplicativo da Web.
Como registrar uma rota de navegação
Caso seu site tenha um aplicativo de página única, você pode usar um
NavigationRoute
para
retornar uma resposta específica para todos
solicitações de navegação.
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);
Sempre que um usuário acessar seu site no navegador, a solicitação da página será
será uma solicitação de navegação e será exibida a página /app-shell.html
em cache.
Observação: você precisa ter a página armazenada em cache via workbox-precaching
ou pela sua
própria etapa de instalação.
Por padrão, isso vai responder a todas as solicitações de navegação. Se você quiser
restringi-lo para responder a um subconjunto de URLs, você pode usar o allowlist
e denylist
para restringir quais páginas corresponderão a esse trajeto.
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);
O único ponto a ser observado é que o denylist
vencerá se um URL estiver em ambos
a allowlist
e a denylist
.
Definir um gerenciador padrão
Se você quiser fornecer um "manipulador" para solicitações que não correspondem a uma rota, é possível definir um gerenciador padrão.
import {setDefaultHandler} from 'workbox-routing';
setDefaultHandler(({url, event, params}) => {
// ...
});
Definir um gerenciador de captura
Caso alguma de suas rotas gere um erro, é possível capturar e degradação suave, definindo um gerenciador de captura.
import {setCatchHandler} from 'workbox-routing';
setCatchHandler(({url, event, params}) => {
...
});
Como definir uma rota para solicitações que não são GET
Por padrão, todas as rotas são consideradas para solicitações GET
.
Se você quiser encaminhar outras solicitações, como POST
, será necessário
para definir o método ao registrar a rota, da seguinte maneira:
import {registerRoute} from 'workbox-routing';
registerRoute(matchCb, handlerCb, 'POST');
registerRoute(new RegExp('/api/.*\\.json'), handlerCb, 'POST');
Geração de registros do roteador
É possível determinar o fluxo de uma solicitação usando os registros do
workbox-routing
, que destaca os URLs que estão sendo processados
pelo Workbox.
Se você precisa de informações mais detalhadas, pode definir o nível de registro como debug
para
acessar registros das solicitações não processadas pelo roteador. Consulte nossa
guia de depuração para mais informações sobre
definindo o nível de registro.
Uso Avançado
Se você quiser ter mais controle sobre quando o roteador do Workbox recebe
você pode criar suas próprias
Router
e chame
são handleRequest()
sempre que quiser usá-lo para responder a uma solicitação.
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.
}
});
Ao usar Router
diretamente, também será necessário usar a classe Route
.
ou qualquer uma das classes estendidas para registrar rotas.
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 a criação de um
workbox-routing.Route
que corresponde a navegador
[solicitações de navegação]https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading#first_what_are_navigation_requests
.
Ela só corresponderá às solicitações recebidas
https://fetch.spec.whatwg.org/#concept-request-mode|mode
é definido como navigate
.
Você pode aplicar essa rota apenas a um subconjunto de solicitações de navegação
usando um ou ambos os parâmetros denylist
e allowlist
.
Propriedades
-
void
Se
denylist
eallowlist
forem fornecidos, odenylist
terão precedência e a solicitação não corresponderá a essa rota.As expressões regulares em
allowlist
edenylist
são combinadas com os dados concatenados [pathname
]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname
e [search
]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search
do URL solicitado.Observação: essas regex podem ser avaliadas em relação a cada URL de destino durante navegação. Evite usar RegExps complexas, Caso contrário, os usuários poderão ter atrasos ao navegar no site.
A função
constructor
tem esta aparência:(handler: RouteHandler, options?: NavigationRouteMatchOptions) => {...}
-
Uma chamada de retorno que retorna uma promessa resultando em uma resposta.
-
NavigationRouteMatchOptions opcional
-
-
RouteHandlerObject opcional
-
HTTPMethod
-
void
A função
setCatchHandler
tem esta aparência:(handler: RouteHandler) => {...}
-
Uma chamada de retorno função que retorna uma promessa resolvendo para uma Resposta
-
NavigationRouteMatchOptions
Propriedades
-
RegExp[] opcional
-
RegExp[] opcional
RegExpRoute
RegExpRoute facilita a criação de uma expressão regular com base
workbox-routing.Route
Para solicitações de mesma origem, a RegExp só precisa corresponder a parte do URL. Para solicitações a servidores de terceiros, é necessário definir uma regex que corresponda início do URL.
Propriedades
-
construtor
void
Se a expressão regular contiver [grupos de captura]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references
, os valores capturados serão passados para aworkbox-routing~handlerCallback
deparams
.A função
constructor
tem esta aparência:(regExp: RegExp, handler: RouteHandler, method?: HTTPMethod) => {...}
-
regExp
RegExp
A expressão regular para correspondência com os URLs.
-
handler
Uma chamada de retorno que retorna uma promessa resultando em uma resposta.
-
method
HTTPMethod opcional
-
retorna
-
-
catchHandler
RouteHandlerObject opcional
-
handler
-
correspondência
-
method
HTTPMethod
-
setCatchHandler
void
A função
setCatchHandler
tem esta aparência:(handler: RouteHandler) => {...}
-
handler
Uma chamada de retorno função que retorna uma promessa resolvendo para uma Resposta
-
Route
Um Route
consiste em um par de funções de callback, "match". e "handler".
A "correspondência" determina se uma rota deve ser usada para "processar" por
solicitação retornando um valor não falso, se possível. O "manipulador" retorno de chamada
é chamado quando há uma correspondência e precisa retornar uma promessa que seja resolvida
para um Response
.
Propriedades
-
construtor
void
Construtor da classe Route.
A função
constructor
tem esta aparência:(match: RouteMatchCallback, handler: RouteHandler, method?: HTTPMethod) => {...}
-
correspondência
Função de callback que determina se a rota corresponde a uma determinada evento
fetch
retornando um valor não falso. -
handler
Uma chamada de retorno que retorna uma promessa resolvendo para uma resposta.
-
method
HTTPMethod opcional
-
retorna
-
-
catchHandler
RouteHandlerObject opcional
-
handler
-
correspondência
-
method
HTTPMethod
-
setCatchHandler
void
A função
setCatchHandler
tem esta aparência:(handler: RouteHandler) => {...}
-
handler
Uma chamada de retorno função que retorna uma promessa resolvendo para uma Resposta
-
Router
O roteador pode ser usado para processar um FetchEvent
usando um ou mais
workbox-routing.Route
, respondendo com Response
se
se há uma rota correspondente.
Se nenhuma rota corresponder a uma determinada solicitação, o roteador usará um "default" se um estiver definido.
Caso a rota correspondente gere um erro, o roteador usa um "catch" caso um deles esteja definido para lidar com problemas e responder com uma Solicitação.
Se uma solicitação corresponder a várias rotas, a mais antiga registrada será ser usada para responder à solicitação.
Propriedades
-
construtor
void
Inicializa um novo roteador.
A função
constructor
tem esta aparência:() => {...}
-
retorna
-
-
rotas
Map<HTTPMethodRoute[]>
-
addCacheListener
void
Adiciona um listener de eventos de mensagem para URLs que serão armazenados em cache na janela. Isso é útil para armazenar em cache os recursos carregados na página antes do momento o service worker começou a controlá-lo.
O formato dos dados da mensagem enviados da janela deve ser o seguinte. Em que a matriz
urlsToCache
pode consistir em strings de URL ou uma matriz de String de URL + objetorequestInit
(o mesmo que você transmitiria parafetch()
).{ type: 'CACHE_URLS', payload: { urlsToCache: [ './script1.js', './script2.js', ['./script3.js', {mode: 'no-cors'}], ], }, }
A função
addCacheListener
tem esta aparência:() => {...}
-
addFetchListener
void
Adiciona um listener de eventos de busca para responder a eventos quando há correspondência de uma rota da solicitação do evento.
A função
addFetchListener
tem esta aparência:() => {...}
-
findMatchingRoute
void
Verifica uma solicitação e um URL (e, opcionalmente, um evento) na lista de rotas registradas e, se houver uma correspondência, retorna o nome trajeto junto com os parâmetros gerados pela correspondência.
A função
findMatchingRoute
tem esta aparência:(options: RouteMatchCallbackOptions) => {...}
-
opções
-
retorna
objeto
Um objeto com as propriedades
route
eparams
. Eles serão preenchidos se uma rota correspondente for encontrada ouundefined
caso contrário.
-
-
handleRequest
void
Aplique as regras de roteamento a um objeto FetchEvent para obter uma resposta de um o manipulador da rota apropriada.
A função
handleRequest
tem esta aparência:(options: object) => {...}
-
opções
objeto
-
evento
ExtendableEvent
O evento que acionou o solicitação.
-
solicitação
Solicitação
A solicitação a ser processada.
-
-
retorna
Promise<Response>
Uma promessa é retornada se uma rota registrada pode processar a solicitação. Se não houver correspondência trajeto e não houver
defaultHandler
,undefined
será retornado.
-
-
registerRoute
void
Registra uma rota com o roteador.
A função
registerRoute
tem esta aparência:(route: Route) => {...}
-
trajeto
A rota a ser registrada.
-
-
setCatchHandler
void
Se uma rota gerar um erro ao processar uma solicitação, essa
handler
será chamado e terá a chance de fornecer uma resposta.A função
setCatchHandler
tem esta aparência:(handler: RouteHandler) => {...}
-
handler
Uma chamada de retorno que retorna uma promessa resultando em uma resposta.
-
-
setDefaultHandler
void
Definir um
handler
padrão que é chamado quando nenhum trajeto explicitamente corresponder à solicitação recebida.Cada método HTTP ("GET", "POST" etc.) tem seu próprio gerenciador padrão.
Sem um manipulador padrão, as solicitações sem correspondência irão para o como se não houvesse um service worker.
A função
setDefaultHandler
tem esta aparência:(handler: RouteHandler, method?: HTTPMethod) => {...}
-
handler
Uma chamada de retorno que retorna uma promessa resultando em uma resposta.
-
method
HTTPMethod opcional
-
-
unregisterRoute
void
Cancela o registro de uma rota com o roteador.
A função
unregisterRoute
tem esta aparência:(route: Route) => {...}
-
trajeto
Rota para cancelar o registro.
-
Métodos
registerRoute()
workbox-routing.registerRoute(
capture: string | RegExp | RouteMatchCallback | Route,
handler?: RouteHandler,
method?: HTTPMethod,
)
Registre facilmente uma RegExp, string ou função com um armazenamento em cache para uma instância de roteador de singleton.
Este método gera um Route para você, se necessário, e
chame workbox-routing.Router#registerRoute
.
Parâmetros
-
capturar
string | RegExp | RouteMatchCallback | Trajeto
Se o parâmetro de captura for um
Route
, todos os outros argumentos serão ignorados. -
handler
RouteHandler opcional
-
method
HTTPMethod opcional
Retorna
-
O
Route
gerado.
setCatchHandler()
workbox-routing.setCatchHandler(
handler: RouteHandler,
)
Se uma rota gerar um erro ao processar uma solicitação, essa handler
será chamado e terá a chance de fornecer uma resposta.
Parâmetros
-
handler
Uma chamada de retorno que retorna uma promessa resultando em uma resposta.
setDefaultHandler()
workbox-routing.setDefaultHandler(
handler: RouteHandler,
)
Definir um handler
padrão que é chamado quando nenhum trajeto explicitamente
corresponder à solicitação recebida.
Sem um manipulador padrão, as solicitações sem correspondência irão para o como se não houvesse um service worker.
Parâmetros
-
handler
Uma chamada de retorno que retorna uma promessa resultando em uma resposta.