Armazenamento para a Web

Há muitas opções diferentes para armazenar dados no navegador. Qual é a melhor para suas necessidades?

As conexões com a Internet podem ser instáveis ou inexistentes quando você está indo de um lugar para outro. suporte off-line e desempenho confiável são recursos comuns em Progressive Web Apps. Mesmo com a tecnologia sem fio perfeita ambientes, o uso criterioso de armazenamento em cache e outras técnicas de armazenamento pode melhorar substancialmente a experiência do usuário. Há várias maneiras de armazenar em cache seus recursos estáticos de aplicativo (HTML, JavaScript, CSS, imagens etc.) e (dados de usuários, artigos de notícias etc.). Mas qual é a melhor solução? Como quanto é possível armazenar? Como evitar a remoção?

O que devo usar?

Confira uma recomendação geral para armazenar recursos:

O IndexedDB e a API Cache Storage são compatíveis com todos os navegadores mais recentes. Ambos são assíncronos e não bloqueiam a linha de execução principal. São acessíveis do objeto window, web workers e service workers, tornando o que facilita o uso delas em qualquer parte do código.

E os outros mecanismos de armazenamento?

Há vários outros mecanismos de armazenamento disponíveis no navegador, mas eles têm uso limitado e podem causar problemas significativos de desempenho.

SessionStorage é específico por guia e tem escopo para vida útil da guia. Pode ser útil para armazenar pequenas quantidades de informações específicas, por exemplo, uma chave IndexedDB. Ele deve ser usado com cuidado, porque ela é síncrona e vai bloquear a linha de execução principal. É limitado a cerca de 5 MB e pode conter apenas strings. Como ele é específico para guias, ela não seja acessível por web workers ou service workers.

LocalStorage precisa ser evitado porque é síncrono e bloqueará a linha de execução principal. Ele tem um limite de cerca de 5 MB e pode conter somente strings. LocalStorage não pode ser acessado por web workers ou serviços trabalhadores

Os cookies têm suas finalidades, mas não devem ser usados para armazenamento. Os cookies são enviados com cada solicitação HTTP. Portanto, ao armazenar algo mais uma pequena quantidade de dados aumentará significativamente o tamanho de cada solicitação da Web. Elas são síncronas e não podem ser acessadas por web workers. Gostei LocalStorage e SessionStorage, os cookies são limitados apenas a strings.

A API File System e a API FileWriter oferecem métodos para leitura e gravação de arquivos em um sistema de arquivos em sandbox. Embora seja assíncrono, não é recomendado, porque é disponível apenas em navegadores baseados no Chromium.

A API File System Access foi criada para torná-la a leitura e a edição de arquivos em seu sistema de arquivos local. O usuário precisa conceder permissão antes que uma página possa ler ou gravar em qualquer arquivo local, e as permissões não são mantidas entre as sessões.

O WebSQL não deve ser usado, e o uso atual precisa ser migrado para IndexedDB. O suporte foi removido de quase todas as principais navegadores da Web. O W3C deixou de manter a especificação do Web SQL em 2010, sem planos de outras atualizações planejadas.

O cache do aplicativo não deve ser usado, e o uso atual deve ser migrados para service workers e para a API Cache. Foi descontinuado, e o suporte será removido dos navegadores em no futuro.

Quantos dados posso armazenar?

Resumindo, muitos, pelo menos algumas centenas de megabytes e potencialmente centenas de gigabytes ou mais. As implementações dos navegadores variam, mas a quantidade de armazenamento disponível geralmente se baseia na quantidade de armazenamento disponível no dispositivo.

  • O Chrome permite que o navegador use até 80% do espaço total em disco. Uma origem pode usam até 60% do espaço total em disco. É possível usar a classe StorageManager API para determinar a cota máxima disponível. Outros apps baseados no Chromium navegadores podem ser diferentes.
    • No modo de navegação anônima, o Chrome reduz o armazenamento que uma origem pode usar a cerca de 5% do espaço total em disco.
    • Se o usuário tiver ativado a opção "Limpar cookies e dados do site ao fechar todos janelas" no Chrome, a cota de armazenamento é reduzida significativamente máximo de aproximadamente 300 MB.
    • Consulte a PR no 3896 para detalhes sobre a implementação do Chrome.
  • O Internet Explorer 10 e posterior pode armazenar até 250 MB e fará com que o quando mais de 10 MB tiverem sido usados.
  • O Firefox permite que o navegador use até 50% do espaço livre em disco. Um eTLD+1 grupo (por exemplo, example.com, www.example.com e foo.bar.example.com) podem usar até 2 GB. Você pode usar o API StorageManager para determinar quanto espaço ainda há disponíveis.
  • O Safari (para computador e dispositivo móvel) parece permitir cerca de 1 GB. Quando o limite for atingido, o Safari solicitará ao usuário, aumentando o limite em 200 MB incrementos. Não encontrei nenhum documento oficial sobre isso.
    • Se um PWA for adicionado à tela inicial no Safari para dispositivos móveis, ele parecerá criar um novo contêiner de armazenamento e nada será compartilhado entre o PWA e Safari para dispositivos móveis. Quando a cota de um PWA instalado for atingida, não parece ser nenhuma maneira de solicitar armazenamento adicional.

Antes, se um site excedesse um determinado limite de dados armazenados, o navegador solicita que o usuário conceda permissão para usar mais dados. Para Por exemplo, se a origem usar mais de 50 MB, o navegador pedirá que o usuário para armazenar até 100 MB e, em seguida, pedir novamente a cada 50 MB.

Atualmente, a maioria dos navegadores modernos não solicita ao usuário e permite que um site usar toda a cota atribuída. A exceção parece ser o Safari, que avisa quando a cota de armazenamento é excedida, solicitando permissão para aumentar a cota alocada. Se uma origem usar mais do que a cota alocada, outras tentativas de gravar dados vai falhar.

Como posso verificar a quantidade de armazenamento disponível?

Em muitos navegadores, você pode usar o API StorageManager para determinar a quantidade de armazenamento para a origem e a quantidade de armazenamento utilizada. Informa o total de bytes usados pelo IndexedDB e pela Cache API e possibilita para calcular o espaço de armazenamento restante aproximado.

if (navigator.storage && navigator.storage.estimate) {
  const quota = await navigator.storage.estimate();
  // quota.usage -> Number of bytes used.
  // quota.quota -> Maximum number of bytes available.
  const percentageUsed = (quota.usage / quota.quota) * 100;
  console.log(`You've used ${percentageUsed}% of the available storage.`);
  const remaining = quota.quota - quota.usage;
  console.log(`You can write up to ${remaining} more bytes.`);
}

O StorageManager ainda não está implemented em todos os navegadores. precisa detectá-lo antes de usá-lo. Mesmo quando está disponível, você precisa ainda detectam erros de cota ultrapassada (veja abaixo). Em alguns casos, é possível a cota disponível para exceder a quantidade real de armazenamento disponível.

Inspecionar

Durante o desenvolvimento, você pode usar as DevTools do seu navegador para inspecionar as diferentes tipos de armazenamento e limpar facilmente todos os dados armazenados.

Um novo recurso foi adicionado no Chrome 88 que permite modificar o armazenamento do site no painel de armazenamento. Com esse recurso, você pode simular dispositivos diferentes e testar o comportamento dos aplicativos quando há baixa disponibilidade de disco diferentes. Acesse Aplicativo e depois Armazenamento, ative a opção Simular cota de armazenamento personalizada e digite um número válido para para simular a cota de armazenamento.

Painel de armazenamento do DevTools.

Enquanto trabalhava neste artigo, escrevi uma ferramenta simples para tente usar rapidamente o máximo de armazenamento possível. É uma forma rápida e fácil testar diferentes mecanismos de armazenamento e ver o que acontece quando você usar toda a sua cota.

Como lidar com o excesso de cota?

O que você deve fazer quando ultrapassa a cota? Acima de tudo, você deve sempre detecte e processe erros de gravação, sejam eles QuotaExceededError ou outra coisa. Depois, dependendo do design do app, decida como lidar com ele. Por exemplo, excluir um conteúdo que não foi acessado há muito tempo, remover com base no tamanho ou fornecer aos usuários uma maneira de escolher o que excluir.

Tanto o IndexedDB quanto a API Cache geram uma DOMError chamada QuotaExceededError quando você exceder a cota disponível.

IndexedDB

Se a origem exceder sua cota, as tentativas de gravação no IndexedDB falhar. O gerenciador onabort() da transação será chamado, transmitindo um evento. O evento vai incluir um DOMException na propriedade de erro. Verificar o erro name retornará QuotaExceededError.

const transaction = idb.transaction(['entries'], 'readwrite');
transaction.onabort = function(event) {
  const error = event.target.error; // DOMException
  if (error.name == 'QuotaExceededError') {
    // Fallback code goes here
  }
};

API Cache

Se a origem excedeu sua cota, tenta gravar na API Cache será rejeitada com um DOMException QuotaExceededError.

try {
  const cache = await caches.open('my-cache');
  await cache.add(new Request('/sample1.jpg'));
} catch (err) {
  if (error.name === 'QuotaExceededError') {
    // Fallback code goes here
  }
}

Como funciona a remoção?

O armazenamento na Web é categorizado em dois buckets, "Melhor esforço" e "Persistente". Melhor esforço significa que o armazenamento pode ser limpo pelo navegador sem que interrompem o usuário, mas é menos durável para dados críticos ou de longo prazo. O armazenamento permanente não é apagado automaticamente quando há pouco espaço. O usuário precisa limpar esse armazenamento manualmente (pelas configurações do navegador).

Por padrão, os dados de um site (incluindo IndexedDB, Cache API etc.) se enquadram a categoria de melhor esforço, ou seja, a menos que um site tenha solicitou um armazenamento permanente, o navegador poderá remover os dados do site de acordo com os próprios critérios, por exemplo, quando o armazenamento do dispositivo for baixo.

A política de remoção para o melhor esforço é:

  • Os navegadores baseados no Chromium vão começar a remover dados quando o navegador acabar de espaço, limpando primeiro todos os dados do site da origem usada menos recentemente depois o próximo, até que o navegador não esteja mais acima do limite.
  • O Internet Explorer 10 ou superior não removerá dados, mas impedirá que a origem escrever mais.
  • O Firefox começará a remover os dados quando o espaço disponível em disco for preenchido, limpar todos os dados do site da origem usada menos recentemente primeiro e, em seguida, em seguida, até que o navegador não esteja mais acima do limite.
  • Anteriormente, o Safari não expulsou os dados, mas recentemente implementou um novo limite de sete dias para todo o armazenamento gravável (veja abaixo).

A partir do iOS e do iPadOS 13.4, e do Safari 13.1 no macOS, há uma limite de sete dias para todo o armazenamento gravável de scripts, incluindo IndexedDB, serviço registro de workers e a API Cache. Isso significa que o Safari vai remover todos conteúdo armazenado em cache após sete dias de uso do Safari, se o usuário não interagem com o site. Esta política de remoção não se aplica a PWAs que foram adicionados à tela inicial. Consulte Bloqueio completo de cookies de terceiros e muito mais no WebKit blog para saber todos os detalhes.

Bônus: por que usar um wrapper para IndexedDB

IndexedDB é uma API de baixo nível que requer configuração significativa antes do uso. o que pode ser particularmente difícil para armazenar dados simples. Ao contrário da maioria das máquinas APIs baseadas em promessas, ela é baseada em eventos. Wrappers de promessas como idb para IndexedDB oculta alguns dos recursos avançados, mas mais O importante é ocultar recursos complexos (por exemplo, transações, controle de versões de esquemas) que acompanha a biblioteca IndexedDB.

Conclusão

Os dias de armazenamento limitado acabaram e os usuários precisam armazenar mais e mais dados. Os sites podem armazenar efetivamente todos os recursos e dados que precisam ser executados. Com a API StorageManager, é possível determinar quanto está disponível para você e quanto você usou. E com armazenamento permanente, a menos que seja removido pelo usuário, você pode protegê-los contra a remoção.

Outros recursos

Obrigado

Um agradecimento especial a Jarryd Goodman, Phil Walton, Eiji Kitamura, Daniel Murphy, Darwin Huang, Josh Bell, Marijn Kruisselbrink e Victor Costan por analisarem neste artigo. Agradecemos a Eiji Kitamura, Addy Osmani e Marc Cohen, que escreveram os artigos originais em que ele se baseia. Eiji escreveu uma ferramenta útil chamado Abuso de armazenamento do navegador, que foi útil para validar comportamento atual. Ele permite que você armazene o máximo de dados possível e veja os limites de armazenamento no seu navegador. Agradecemos a Francois Beaufort, que fez a escavação no Safari para descobrir seus limites de armazenamento.

A imagem principal é de Guillaume Bolduc, em Unsplash: