Armazenando…

O armazenamento em cache é uma ferramenta poderosa. Isso torna seus apps menos dependentes das condições da rede. Com o bom uso de caches, você pode disponibilizar seu app da Web off-line e exibir seus recursos o mais rápido possível em qualquer condição de rede. Conforme mencionado em Recursos e dados, você pode decidir a melhor estratégia para armazenar os recursos necessários em cache. Para gerenciar o cache, seu service worker interage com a API Cache Storage.

Compatibilidade com navegadores

  • 43
  • 16
  • 41
  • 11.1

Origem

A API Cache Storage está disponível em diferentes contextos:

  • O contexto da janela (a linha de execução principal do PWA).
  • O service worker.
  • Quaisquer outros workers que você usar.

Uma vantagem de gerenciar seu cache usando service workers é que o ciclo de vida dele não está vinculado à janela, o que significa que você não está bloqueando a linha de execução principal. Para usar a API Cache Storage, a maioria desses contextos precisa estar relacionada a uma conexão TLS.

O que armazenar em cache

A primeira pergunta que você pode ter sobre o armazenamento em cache é o que deve ser armazenado. Embora não haja uma resposta única para essa pergunta, você pode começar com todos os recursos mínimos necessários para renderizar a interface do usuário.

Esses recursos precisam incluir:

  • O HTML da página principal (o start_url do seu aplicativo).
  • folhas de estilo CSS necessárias para a interface do usuário principal.
  • Imagens usadas na interface do usuário.
  • Arquivos JavaScript necessários para renderizar a interface do usuário.
  • Dados, como um arquivo JSON, necessários para renderizar uma experiência básica.
  • Fontes da Web.
  • Em um aplicativo de várias páginas, outros documentos HTML que você queira veicular rapidamente ou off-line.

Pronto para o modo off-line

Embora a funcionalidade off-line seja um dos requisitos de um Progressive Web App, é essencial entender que nem todo PWA precisa de uma experiência off-line completa, por exemplo, soluções de jogos em nuvem ou apps de criptoativos. Portanto, não há problema em oferecer uma interface do usuário básica que oriente os usuários nessas situações.

O PWA não deve renderizar uma mensagem de erro do navegador informando que o mecanismo de renderização da Web não conseguiu carregar a página. Em vez disso, use seu service worker para mostrar suas próprias mensagens, evitando um erro genérico e confuso no navegador.

Existem muitas estratégias de armazenamento em cache diferentes, dependendo das necessidades do seu PWA. Por isso, é importante projetar o uso do cache para fornecer uma experiência rápida e confiável. Por exemplo, se todos os seus recursos de link para app são transferidos por download rapidamente, não consomem muito espaço e não precisam ser atualizados em todas as solicitações, armazenar todos os recursos em cache é uma estratégia válida. Se, por outro lado, você tiver recursos que precisem estar na versão mais recente, é recomendável não armazená-los em cache.

Como usar a API

Use a API Cache Storage para definir um conjunto de caches na sua origem, cada um identificado com um nome de string que você pode definir. Acesse a API usando o objeto caches, e o método open permite a criação ou a abertura de um cache já criado. O método open retorna uma promessa para o objeto de cache.

caches.open("pwa-assets")
.then(cache => {
  // you can download and store, delete or update resources with cache arguments
});

Fazer o download e armazenar recursos

Para solicitar que o navegador faça o download e armazene os recursos, use os métodos add ou addAll. O método add faz uma solicitação e armazena uma resposta HTTP e addAll, um grupo de respostas HTTP como uma transação com base em uma matriz de solicitações ou URLs.

caches.open("pwa-assets")
.then(cache => {
  cache.add("styles.css"); // it stores only one resource
  cache.addAll(["styles.css", "app.js"]); // it stores two resources
});

A interface de armazenamento em cache armazena toda a resposta, incluindo todos os cabeçalhos e o corpo. Consequentemente, você pode recuperá-la usando uma solicitação HTTP ou um URL como chave. Você vai aprender a fazer isso no capítulo "Veiculação".

Quando armazenar em cache

No PWA, você é responsável por decidir quando armazenar arquivos em cache. Embora uma abordagem seja armazenar o maior número possível de recursos quando o service worker estiver instalado, essa geralmente não é a melhor ideia. O armazenamento em cache de recursos desnecessários desperdiça largura de banda e espaço de armazenamento e pode fazer com que o app disponibilize recursos desatualizados indesejados.

Não é necessário armazenar todos os recursos em cache de uma só vez. É possível armazenar recursos em cache várias vezes durante o ciclo de vida do PWA, como:

  • Na instalação do service worker.
  • Após o carregamento da primeira página.
  • Quando o usuário navega para uma seção ou rota.
  • Quando a rede está inativa.

É possível solicitar o armazenamento em cache de novos arquivos na linha de execução principal ou no contexto do service worker.

Como armazenar recursos em cache em um service worker

Um dos cenários mais comuns é armazenar em cache um conjunto mínimo de recursos quando o service worker estiver instalado. Para fazer isso, use a interface de armazenamento em cache no evento install do service worker.

Como a linha de execução de service worker pode ser interrompida a qualquer momento, é possível solicitar que o navegador aguarde a promessa de addAll ser concluída para aumentar a oportunidade de armazenar todos os recursos e manter o app consistente. Confira no exemplo a seguir como fazer isso usando o método waitUntil do argumento de evento recebido no listener de eventos do service worker.

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", event => {
   event.waitUntil(
      caches.open("pwa-assets")
      .then(cache => {
         return cache.addAll(urlsToCache);
      });
   );
});

O método waitUntil() recebe uma promessa e solicita que o navegador aguarde a tarefa da promessa ser resolvida (atendida ou com falha) antes de encerrar o processo do service worker. Talvez seja necessário encadear promessas e retornar as chamadas add() ou addAll() para que um único resultado chegue ao método waitUntil().

Também é possível processar promessas usando a sintaxe async/await. Nesse caso, é necessário criar uma função assíncrona que possa chamar await e que retorne uma promessa para waitUntil() depois que ela for chamada, como no exemplo a seguir:

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", (event) => {
   let cacheUrls = async () => {
      const cache = await caches.open("pwa-assets");
      return cache.addAll(urlsToCache);
   };
   event.waitUntil(cacheUrls());
});

Solicitações de vários domínios e respostas opacas

O PWA pode fazer o download e armazenar em cache recursos da sua origem e de vários domínios, como conteúdo de CDNs de terceiros. Com um aplicativo de vários domínios, a interação do cache é muito semelhante às solicitações de mesma origem. A solicitação é executada e uma cópia da resposta é armazenada em seu cache. Assim como os outros recursos armazenados em cache, eles só estão disponíveis para serem usados na origem do app.

O recurso será armazenado como uma resposta opaca, ou seja, seu código não será capaz de ver nem modificar o conteúdo ou os cabeçalhos dessa resposta. Além disso, as respostas opacas não expõem o tamanho real na API Storage, o que afeta as cotas. Alguns navegadores expõem tamanhos grandes, como 7 MB, independentemente de o arquivo ter apenas 1 Kb.

Atualizar e excluir recursos

É possível atualizar recursos usando cache.put(request, response) e excluir recursos com delete(request).

Consulte a documentação do objeto de cache para mais detalhes.

Como depurar o armazenamento em cache

Muitos navegadores oferecem uma forma de depurar o conteúdo do armazenamento em cache na guia "Application" do DevTools. Lá, você pode ver o conteúdo de cada cache dentro da origem atual. Veja mais informações sobre essas ferramentas no capítulo Ferramentas e depuração.

O Chrome DevTools depura o conteúdo do armazenamento em cache.

Recursos