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 seus recursos, mas o tempo envolvido pode ser substancial, às vezes de até meio segundo quando a CPU está lenta ou funcionando em um estado limitado devido a condições do ambiente. O ganho de desempenho ao evitar a rede provavelmente vai compensar esse tempo de inicialização quando as respostas de navegação são disponibilizadas por 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 de navegação

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

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

Isso não é o ideal, mas é possível corrigi-lo 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 barra azul é "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, ele não é um recurso que precisa ser ativado em todas as situações. Em particular, os sites que usam um shell do aplicativo pré-armazenado em cache não precisam do pré-carregamento de navegação, porque o cache exibe a solicitação de navegação para a marcação do shell do aplicativo sem qualquer latência de navegação. Nesses casos, a resposta pré-carregada será desperdiçada, o que não é muito 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 de acordo com coisas como o estado de autenticação. As solicitações de navegação para esses casos podem usar uma estratégia que prioriza a rede (ou até mesmo uma apenas de rede). Por isso, 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 usa 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á-la diretamente nesta ótima explicação de Jake Archibald (link em inglês).

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

A partir daqui, os benefícios do pré-carregamento de navegação são alcançados em navegadores compatíveis usando o Workbox para processar solicitações de navegação usando 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?

Nos builds de desenvolvimento, o Workbox registra muito sobre o que ele faz. Se você quiser verificar se o pré-carregamento da navegação está funcionando no Workbox, abra o console em um navegador compatível durante uma solicitação de navegação. Uma mensagem de registro será exibida com as seguintes informações:

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

Por padrão, essa geração de registros não será exibida em builds de produção. Portanto, ela não será exibida quando você implantar o service worker na produção, mas é uma ótima maneira de verificar se o pré-carregamento de 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 é necessário personalizar as respostas pré-carregadas em um back-end de 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 do aplicativo escolhido, verifique esse cabeçalho e modifique a resposta para atender às suas necessidades. Se o valor padrão do cabeçalho apresentar problemas por qualquer motivo, altere-o no contexto da janela. Saiba que qualquer trabalho que você fizer no servidor para ler esse cabeçalho depende de você e está 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 da navegação com muito menos trabalho. Para mais detalhes sobre o módulo workbox-navigation-preload, consulte a documentação de referência dele.