Como forçar um tempo limite de rede

Há momentos em que você tem uma conexão de rede, mas ela é muito lenta, ou a conexão mentira que você está on-line. Nessas situações, em que há um service worker, uma estratégia de armazenamento em cache que prioriza a rede pode levar muito tempo para receber uma resposta da rede, ou a solicitação trava (e os ícones de carregamento de carregamento giram sem parar) até aparecer uma página de erro.

Seja qual for a situação, há casos em que seria preferível retornar à última resposta armazenada em cache para um recurso ou uma página após um determinado período. No entanto, esse é outro problema que o Workbox pode resolver.

Como usar o networkTimeoutSeconds

É possível forçar um tempo limite para solicitações de rede usando as estratégias NetworkFirst ou NetworkOnly. Essas estratégias oferecem uma opção networkTimeoutSeconds, que especifica o número de segundos que o service worker precisa aguardar a resposta da rede antes de ser restabelecida e retornar a última versão armazenada em cache:

// sw.js
import { NetworkFirst } from 'workbox-strategies';
import { registerRoute, NavigationRoute } from 'workbox-routing';

// Only wait for three seconds before returning the last
// cached version of the requested page.
const navigationRoute = new NavigationRoute(new NetworkFirst({
  networkTimeoutSeconds: 3,
  cacheName: 'navigations'
}));

registerRoute(navigationRoute);

O código acima instrui o service worker a sair em qualquer solicitação de navegação que prioriza a rede e a usar a última versão em cache após três segundos. Quando usado com solicitações de navegação, isso garante acesso à última resposta armazenada em cache de qualquer página visitada anteriormente.

No entanto, e se a página que você está acessando não tiver uma resposta mais antiga no cache? Nesses casos, você pode estabelecer uma resposta substituta para uma página HTML off-line genérica:

import {registerRoute, NavigationRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

// Hardcode the fallback cache name and the offline
// HTML fallback's URL for failed responses
const FALLBACK_CACHE_NAME = 'offline-fallback';
const FALLBACK_HTML = '/offline.html';

// Cache the fallback HTML during installation.
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(FALLBACK_CACHE_NAME).then((cache) => cache.add(FALLBACK_HTML)),
  );
});

// Apply a network-only strategy to navigation requests.
// If offline, or if more than five seconds pass before there's a
// network response, fall back to the cached offline HTML.
const networkWithFallbackStrategy = new NetworkOnly({
  networkTimeoutSeconds: 5,
  plugins: [
    {
      handlerDidError: async () => {
        return await caches.match(FALLBACK_HTML, {
          cacheName: FALLBACK_CACHE_NAME,
        });
      },
    },
  ],
});

// Register the route to handle all navigations.
registerRoute(new NavigationRoute(networkWithFallbackStrategy));

Isso funciona porque, quando você usa networkTimeoutSeconds em uma estratégia NetworkFirst, seu gerenciador retornará uma resposta de erro se o tempo limite for atingido e não houver uma correspondência de cache para o URL. Se isso acontecer, o plug-in do Workbox handlerDidError pode fornecer uma resposta genérica como substituto.

Quanto tempo é demais esperar?

Ao forçar um tempo limite para solicitações, principalmente para solicitações de navegação, é bom encontrar o equilíbrio certo entre não deixar o usuário esperar por muito tempo e não atingir o tempo limite muito rapidamente. Se você esperar demais, poderá haver o risco de os usuários com conexões lentas serem rejeitados antes do tempo limite. Tempo limite muito rápido, e você pode acabar exibindo desnecessariamente conteúdo obsoleto no cache.

A resposta certa é "depende". Se você gerencia um site como um blog e não atualiza o conteúdo com muita frequência, a resposta certa é errar pelo lado de não esperar muito, já que tudo o que está no cache provavelmente está "atualizado" o suficiente. No entanto, para sites e apps da Web mais interativos, talvez seja melhor esperar um pouco mais e evitar a exibição de dados desatualizados do cache do service worker com muita ansiedade.

Se você estiver registrando métricas em campo, confira o 75o percentil das pontuações de Tempo para primeiro byte (TTFB) e Primeira exibição de conteúdo (FCP) para ter uma noção de onde os tempos de espera mais longos para solicitações de navegação podem estar entre sua base de usuários. Isso pode lhe dar uma ideia de onde traçar a linha.