Armazenar dados no dispositivo

O PWA (progressive Aplicativos Web) oferece opções robustas para armazenar dados localmente para permitir que os usuários continuem funcionando mesmo que a conexão de rede se torne instável ou fique offline.

Há várias maneiras pelas quais um PWA pode armazenar dados em um dispositivo, como armazenamento local, API de Cache ou IndexedDB.

A tabela a seguir descreve as diferentes opções e o restante deste artigo entra em mais detalhes e cenários de uso para cada opção.

Opção de armazenamento Descrição
Armazenamento Web O Armazenamento Web tem dois tipos: sessão e local. O Armazenamento Web é útil para armazenar pequenas quantidades de dados do código de front-end do aplicativo. Os dados são estruturados como pares de valor-chave e só estão disponíveis para a origem do aplicativo atual. No caso do armazenamento de sessão, os dados são limpos quando a sessão termina, por exemplo, quando o aplicativo é fechado ou quando o usuário navega para outra origem na mesma janela ou guia. O armazenamento local persiste até que o aplicativo remova os dados.
IndexedDB IndexedDB é uma API para armazenar quantidades maiores de dados estruturados. A API é assíncrona e pode ser usada tanto no código de front-end do aplicativo quanto no código do trabalho de serviço. Use a API IndexedDB para armazenar uma quantidade significativa de dados estruturados no cliente ou dados binários, como objetos de mídia criptografados ou arquivos.
Cache A API de Cache pode ser usada para gerenciar recursos armazenados em cache. A API de Cache é baseada em promessas e permite que os desenvolvedores armazenem e recuperem muitos recursos da Web — HTML, CSS, JavaScript, imagens, JSON e assim por diante. Normalmente, a API de Cache é usada no contexto de um trabalho de serviço, mas também está disponível para o código de front-end do aplicativo.
Acesso ao sistema de arquivos A API de Acesso ao Sistema de Arquivos permite que seu PWA leia arquivos e pastas no dispositivo do usuário e salve as alterações de volta para eles.

Observação: não use WebSQL ou Cache de Aplicativo. Embora sejam dois outros mecanismos de armazenamento do navegador, ambos foram preteridos. Em vez de WebSQL, use IndexedDB. Em vez de Cache de Aplicativo, use a API de Cache.

Armazenamento Web

O Armazenamento Web é útil para armazenar pequenas quantidades de dados de cadeia de caracteres no dispositivo do usuário. A simplicidade do sistema de pares de valor-chave do Armazenamento Web facilita o uso.

O Armazenamento Web funciona de forma síncrona apenas no thread principal do seu aplicativo. Isso significa que o Armazenamento Web não está disponível para uso em trabalhadores de serviço e que o uso intenso do Armazenamento Web pode criar problemas de desempenho para seu aplicativo.

Cada tipo de Armazenamento Web, sessão e local é mantido como um armazenamento de dados separado isolado para o domínio que o criou.

  • sessionStorage persiste apenas pela duração da sessão - por exemplo, enquanto o navegador está aberto, o que inclui quando a página é atualizada.
  • localStorage persiste até que os dados sejam removidos pelo código do aplicativo, pelo usuário ou pelo navegador.

O código a seguir mostra como usar localStorage, que é semelhante a como sessionStorage é usado:

const browserInformation = {
  name: 'Microsoft Edge',
  version: 108
};

localStorage.setItem('browser', JSON.stringify(browserInformation));

O código acima armazena um objeto JavaScript como uma cadeia de caracteres JSON no localStorage uso do setItem() método e atribui uma chave igual a browser. Você pode recuperar as informações localStorage usando o getItem() método, conforme mostrado abaixo:

const value = localStorage.getItem('browser');

const browserInformation = JSON.parse(value);

Para saber mais, confira API de Armazenamento Web no MDN.

IndexedDB

IndexedDB é uma API assíncrona para armazenar dados estruturados que podem ser usados no código de front-end ou no código de trabalho de serviço do aplicativo. Use a API IndexedDB para armazenar uma quantidade significativa de dados estruturados no cliente ou dados binários, como objetos de mídia criptografados ou arquivos.

IndexedDB é a melhor opção para armazenar dados em seu PWA, pois o uso da API não reduz a velocidade do aplicativo bloqueando o thread principal e pode ser usado tanto do código front-end do aplicativo quanto do trabalho de serviço.

O uso do IndexedDB é mais complexo do que o uso do Armazenamento Web e requer as seguintes etapas para armazenar dados:

  1. Abra um banco de dados usando a window.indexedDB.open() função.
  2. Crie um repositório de objetos no banco de dados usando a IDBDatabase.createObjectStore() função.
  3. Inicie uma transação para armazenar dados usando a IDBDatabase.transaction() função.
  4. Aguarde a conclusão da operação, ouvindo um evento.

Para saber mais e exibir exemplos de código, consulte Usando IndexedDB no MDN.

Cache

A API de Cache é um sistema para armazenar e recuperar solicitações e respostas de rede no código de front-end ou no trabalho de serviço do aplicativo. Ele pode ser usado para armazenar ativos, como imagens e arquivos, localmente no dispositivo do usuário. Isso pode fazer com que seu aplicativo funcione mesmo quando estiver offline ou melhorar seu desempenho reduzindo o número de solicitações de rede necessárias para renderizar o aplicativo.

O snippet de código a seguir mostra como ouvir o fetch evento em um trabalho de serviço e armazenar a resposta do servidor usando a API de Cache:

self.addEventListener("fetch", event => {
  async function cacheAndReturnRequest() {
    // Get the response from the server.
    const fetchResponse = await fetch(event.request.url);
    // Open the app's cache.
    const cache = await caches.open("cache-name");
    // Put the response in cache.
    cache.put(event.request.url, fetchResponse.clone());
    // And return the response.
    return fetchResponse.
  }

  event.respondWith(cacheAndReturnRequest());
});

Para descobrir outros cenários úteis de API de Cache, consulte Usar Os Trabalhadores do Serviço para gerenciar solicitações de rede.

Acesso ao sistema de arquivos

A API de Acesso ao Sistema de Arquivos possibilita que seu aplicativo acesse arquivos no dispositivo do usuário de forma semelhante aos aplicativos nativos. Ele pode ser usado para criar aplicativos que podem ler e gravar arquivos, como editores de texto ou imagem.

Para abrir um arquivo do dispositivo do usuário, use a showOpenFilePicker() função:

openFileButton.addEventListener("click", async () => {
  const fileHandles = await window.showOpenFilePicker();
});

Para saber mais, confira Window.showOpenFilePicker() no MDN.

A API de Acesso ao Sistema de Arquivos também pode ser associada ao recurso tratamento de arquivos PWA para registrar seu aplicativo como um manipulador de tipos de arquivo específicos e, portanto, sentir-se mais nativo para os usuários. Para saber mais, confira Manipular arquivos no Aplicativos Web Progressivo.

A API de Acesso ao Sistema de Arquivos privada de origem é uma variação da API de Acesso do Sistema de Arquivos que se destina a fornecer mais privacidade para os usuários. Ele permite que os aplicativos acessem arquivos no dispositivo do usuário também, mas somente dentro de um diretório específico que seja privado para a origem do aplicativo. Além disso, essa API não se destina a facilitar o acesso dos usuários ao diretório privado usando o explorador de arquivos.

Para abrir um arquivo do sistema de arquivos privado de origem, use a navigator.storage API baseada em promessas:

// Get the origin-private directory handle.
const root = await navigator.storage.getDirectory();
// Get the handle for a file in the directory.
const fileHandle = await root.getFileHandle("my-file.txt");

Cota de Armazenamento

No Microsoft Edge, o armazenamento local e de sessão é limitado a cerca de 5MB cada.

Outros tipos de armazenamento de dados, como IndexedDB, API de Cache ou API de Acesso ao Sistema de Arquivos Privados de Origem, podem usar até 60% do espaço total em disco no dispositivo. Por exemplo, se o dispositivo em que seu aplicativo está em execução tiver um disco de 64 GB, o Microsoft Edge permitirá que seu aplicativo armazene até cerca de 38 GB de dados.

Observe que o espaço livre que está realmente disponível no dispositivo pode ser menor que a cota de armazenamento de 60%. Por exemplo, se o dispositivo em que seu aplicativo está em execução tiver um disco de 64 GB, mas 50GB já for usado pelo sistema operacional e outros arquivos, seu aplicativo só poderá armazenar 14GB de dados, mesmo que a cota de armazenamento ainda seja de 38GB.

Você pode usar navigator.storage.estimate() para perguntar à API do Gerenciador de Armazenamento qual é a cota de armazenamento para a origem do aplicativo e quanto dele já é usado. Para saber mais, confira StorageManager.estimate() no MDN.

Tentar armazenar mais dados do que está disponível ou permitido resulta em um erro JavaScript. Seu código deve capturar esse erro usando try...catch instruções. O snippet de código abaixo mostra como capturar um erro de cota excedido ao armazenar dados usando o Armazenamento Web:

try {
  localStorage.setItem('foo', 'bar');
} catch (e) {
  // Code that handles the lack of storage space.
}

Despejo de dados

Quando o dispositivo do usuário começar a ficar com pouco espaço em disco disponível, também conhecido como pressão de armazenamento, o Microsoft Edge começará a despejar dados não persistentes.

Isso significa que os dados armazenados pelo aplicativo usando a API de Cache, IndexedDB, a API de Acesso ao Sistema de Arquivos Privados de Origem ou o Armazenamento Web podem ser despejados.

Por padrão, os dados que seu aplicativo armazena não são considerados persistentes e podem ser despejados quando há pressão de armazenamento. Se seu aplicativo armazenar dados críticos, use a função para tornar o navigator.storage.persist() armazenamento do aplicativo persistente. O armazenamento persistente só pode ser limpo pelo usuário. Para saber mais, consulte StorageManager.persist() no MDN.