Pré-carregamento de navegação para HTML que prioriza a rede

Quando um service worker processa eventos fetch, o navegador espera que o service worker forneça uma resposta. Embora a latência da solicitação de rede seja uma grande parte da espera, o navegador também pode precisar aguardar a inicialização do service worker e disparar callbacks de eventos fetch.

O tempo de inicialização varia de acordo com o dispositivo e as capacidades dele, mas o tempo envolvido pode ser substancial, às vezes de até meio segundo quando a CPU está lenta ou está funcionando em um estado limitado devido às condições do ambiente. O ganho de desempenho de evitar a rede provavelmente vai superar esse tempo de inicialização quando as respostas de navegação forem veiculadas em uma instância Cache. Para solicitações de navegação que vão para a rede, a introdução de um service worker pode criar um atraso perceptível.

Entrar no pré-carregamento da navegação

O pré-carregamento de navegação é um recurso do service worker que resolve o atraso causado pelo tempo de inicialização dele. Sem o pré-carregamento de navegação ativado, a inicialização do service worker e a solicitação de navegação que ele processa ocorrerão consecutivamente:

Uma barra amarela e azul, com dois segmentos mostrando ações consecutivas. O primeiro segmento, em amarelo, diz "Inicialização de SW" e o segmento azul diz "Solicitação de navegação".

Isso não é o ideal, mas é possível corrigir isso ativando o pré-carregamento da navegação, o que garante que a inicialização do service worker e a solicitação de navegação ocorram simultaneamente:

Duas barras empilhadas uma sobre a outra e alinhadas à esquerda, representando duas ações simultâneas. A barra amarela é identificada como "Inicialização de SW" e a azul é identificada como "Solicitação de navegação".

Embora o pré-carregamento de navegação seja uma ótima otimização de desempenho para sites que usam service workers, esse não é um recurso que você deve ativar em todas as situações. Em particular, os sites que usam um shell de app pré-armazenado não precisam de pré-carregamento de navegação, já que o cache atende à solicitação de navegação para a marcação do shell do app sem qualquer latência de navegação. Nesses casos, a resposta pré-carregada vai para o lixo, o que não é nada bom.

O melhor momento para usar o pré-carregamento de navegação é quando um site não pode pré-armazenar em cache o HTML. Pense em sites em que as respostas de marcação são dinâmicas e variam com aspectos como o estado de autenticação. As solicitações de navegação para eles podem usar uma estratégia que prioriza a rede (ou até mesmo uma somente rede), e é aí que o pré-carregamento de navegação pode fazer uma grande diferença.

Como usar o pré-carregamento de navegação no Workbox

É complicado usar o pré-carregamento de navegação diretamente em um service worker que não tem a tecnologia do Workbox. Primeiro, ele não é compatível com todos os navegadores. Em segundo lugar, pode ser difícil acertar. Aprenda a usá-lo diretamente nesta ótima explicação de Jake Archibald.

A caixa de trabalho simplifica o uso do pré-carregamento de navegação porque o método enable do módulo workbox-navigation-preload faz as verificações de suporte de recursos necessárias, além de criar o listener de eventos activate para ativá-lo para você.

Os benefícios do pré-carregamento de navegação são aproveitados no suporte a navegadores usando o Workbox para processar solicitações de navegação com um gerenciador de estratégia que prioriza a rede:

import * as navigationPreload from 'workbox-navigation-preload';
import {NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {registerRoute, NavigationRoute, Route} from 'workbox-routing';
import {precacheAndRoute} from 'workbox-precaching';

// Precache the manifest
precacheAndRoute(self.__WB_MANIFEST);

// Enable navigation preload
navigationPreload.enable();

// Create a new navigation route that uses the Network-first, falling back to
// cache strategy for navigation requests with its own cache. This route will be
// handled by navigation preload. The NetworkOnly strategy will work as well.
const navigationRoute = new NavigationRoute(new NetworkFirst({
  cacheName: 'navigations'
}));

// Register the navigation route
registerRoute(navigationRoute);

// Create a route for image, script, or style requests that use a
// stale-while-revalidate strategy. This route will be unaffected
// by navigation preload.
const staticAssetsRoute = new Route(({request}) => {
  return ['image', 'script', 'style'].includes(request.destination);
}, new StaleWhileRevalidate({
  cacheName: 'static-assets'
}));

// Register the route handling static assets
registerRoute(staticAssetsRoute);

Quando o pré-carregamento de navegação está ativado, o Workbox responde às solicitações de navegação que usam as estratégias NetworkFirst ou NetworkOnly com a resposta pré-carregada.

Como saber se o pré-carregamento da navegação está funcionando?

Em builds de desenvolvimento, o Workbox registra muitas suas funções. Se você quiser verificar se o pré-carregamento de navegação está funcionando no Workbox, abra o console em um navegador com suporte durante uma solicitação de navegação. Você vai ver uma mensagem de registro dizendo o seguinte:

Uma captura de tela dos registros do Workbox no console do DevTools do Chrome. As mensagens são lidas de cima para baixo: "O roteador está respondendo a "/"", "Usando uma solicitação de navegação pré-carregada para /" e "Usando o NetworkFirst para responder a /"

Essa geração de registros não será visível em builds de produção por padrão, ou seja, não vai aparecer quando você implantar o service worker na produção, mas é uma ótima maneira de verificar se o pré-carregamento da navegação está funcionando, entre outras coisas.

Como personalizar respostas pré-carregadas

Ao usar o pré-carregamento de navegação, pode haver cenários em que seja necessário personalizar as respostas pré-carregadas no back-end de um aplicativo. Os service workers que transmitem conteúdo parcial da rede são um cenário em que isso pode ser útil.

Nesses casos, vale a pena saber que as solicitações de pré-carregamento são enviadas com um cabeçalho Service-Worker-Navigation-Preload definido com um valor padrão de true:

Service-Worker-Navigation-Preload: true

Em seguida, no back-end de seu aplicativo, você pode verificar esse cabeçalho e modificar a resposta para atender às suas necessidades. Se o valor padrão do cabeçalho for problemático por algum motivo, é possível mudá-lo no contexto da janela. Qualquer trabalho de leitura desse cabeçalho no servidor depende de você, e fora do escopo do Workbox.

Conclusão

O pré-carregamento de navegação é difícil de acertar quando usado diretamente, mas esse trabalho árduo vale a pena para garantir que um service worker não impeça o navegador de fazer solicitações de navegação. Graças ao Workbox, você pode aproveitar o pré-carregamento de navegação com muito menos trabalho. Para mais detalhes sobre o módulo workbox-navigation-preload, consulte a documentação de referência.