Dados Off-line em PWA

PWA
Tempo de leitura: 4 minutos

Dados Off-line em PWA: Para que um Progressive Web App (PWA) seja verdadeiramente confiável (reliable), ele precisa não apenas do App Shell estático (CSS, JS) em cache, mas também da capacidade de armazenar e gerenciar dados dinâmicos para o modo offline. É aqui que entra o IndexedDB.

O IndexedDB é uma API de armazenamento no lado do cliente que funciona como um banco de dados NoSQL embutido no navegador. Ele é ideal para grandes volumes de dados estruturados, fornecendo a base para o funcionamento completo de um PWA, mesmo sem conectividade.

1. 🆚 IndexedDB vs. Outras APIs de Armazenamento

Embora existam outras APIs, o IndexedDB é a escolha padrão para PWAs focados em dados complexos:

APIModeloCapacidade de ArmazenamentoTipo de OperaçãoIdeal Para…
IndexedDBObjeto/ChaveGigabytes (Alto)Assíncrona (Promises)Dados Estruturados, Aplicações complexas.
Local StorageChave-ValorKilobytes (Baixo)SíncronaPreferências de usuário, Tokens simples.
Cache APIRequest-ResponseAltoAssíncrona (Promises)Arquivos estáticos (Assets).

Foco: IndexedDB é o único que oferece a capacidade, o modelo de dados e a natureza assíncrona necessários para armazenar um catálogo de produtos ou um histórico de mensagens.

2. 🏛️ Estrutura do IndexedDB

A arquitetura do IndexedDB segue um modelo semelhante ao de bancos de dados:

  1. Banco de Dados (Database): O contêiner principal (ex: 'meu-app-db'). É aberto por versão.
  2. Object Stores (ObjectStore): Onde os dados são realmente armazenados, semelhante a tabelas em um banco relacional (ex: 'usuarios', 'produtos').
  3. Índices (Indexes): Usados para acelerar a busca de dados que não sejam pela chave primária.
  4. Transações (Transactions): Garantem que as operações (leitura/escrita) sejam atômicas, mantendo a integridade dos dados.

3. ⚙️ Operações Básicas (Sintaxe Moderna com Promises)

O IndexedDB é baseado em requisições (request.onsuccess, request.onerror), que são naturalmente assíncronas. Bibliotecas externas (como Dexie.js) ou funções wrapper são frequentemente usadas para convertê-lo em sintaxe moderna baseada em Promise/async/await.

A. Criando e Abrindo o Banco de Dados

O onupgradeneeded é o único local onde você pode criar ou alterar a estrutura do banco (Object Stores). Ele é chamado se a versão fornecida (1) for maior que a versão atual do banco de dados do navegador.

JavaScript

const DB_NAME = 'meu-pwa-db';
const STORE_NAME = 'produtos';

const openDB = () => {
  return new Promise((resolve, reject) => {
    const request = window.indexedDB.open(DB_NAME, 1);

    request.onerror = (event) => reject('Erro ao abrir DB.');
    
    request.onsuccess = (event) => resolve(event.target.result);

    request.onupgradeneeded = (event) => {
      const db = event.target.result;
      // Cria a Object Store, definindo 'id' como chave primária
      db.createObjectStore(STORE_NAME, { keyPath: 'id' }); 
    };
  });
};

B. Escrevendo Dados (Adicionar/Atualizar)

Todas as operações de escrita precisam de uma Transação no modo 'readwrite'.

JavaScript

// Exemplo de como adicionar/atualizar dados (put)
async function putData(data) {
  const db = await openDB();
  // Inicia a transação de leitura/escrita
  const transaction = db.transaction(STORE_NAME, 'readwrite');
  const store = transaction.objectStore(STORE_NAME);

  return new Promise((resolve, reject) => {
    const request = store.put(data);
    
    request.onsuccess = () => resolve('Dado salvo com sucesso.');
    request.onerror = (event) => reject(event.target.error);

    // Opcional: Garante que a Promise só resolva após a transação ser concluída
    transaction.oncomplete = resolve; 
  });
}

C. Lendo Dados (Busca por Chave)

A leitura requer uma transação no modo padrão 'readonly'.

JavaScript

// Exemplo de busca de dados por chave primária (id)
async function getDataById(id) {
  const db = await openDB();
  const transaction = db.transaction(STORE_NAME, 'readonly');
  const store = transaction.objectStore(STORE_NAME);

  return new Promise((resolve, reject) => {
    const request = store.get(id);

    request.onsuccess = (event) => resolve(event.target.result);
    request.onerror = (event) => reject(event.target.error);
  });
}

✅ Conclusão

Dados Off-line em PWA: O IndexedDB é a solução fundamental para a persistência de grandes volumes de dados estruturados em PWAs. Ao contrário do Local Storage, ele é assíncrono e robusto, sendo a tecnologia ideal para construir a camada de dados offline da sua aplicação. Dominar a criação do Banco de Dados, Object Stores e o uso de Transações permite que você crie experiências de usuário que permanecem ricas e funcionais, mesmo quando a conexão com a internet falha.

Toda jornada tem um início, e o início para se tornar um desenvolvedor web é dominar as seguintes tecnologias, que você encontra aqui mesmo:

HTML
HTML
CSS
CSS
Javascript
JavaScript

E se você gosta do nosso conteúdo, não deixe de contribuir adquirindo os serviços e produtos dos nossos apoiadores e empresas que somos associados:

Hospedagem Hostinger
Ofertas Amazon
Amazon Prime

Author: Thiago Rossi
Com mais de 20 anos de jornada na tecnologia, minha trajetória evoluiu do ensino técnico à arquitetura de sistemas complexos. Hoje, foco minha expertise no desenvolvimento de soluções de Inteligência Artificial nativa e análise de dados públicos, utilizando o ecossistema PHP para transformar dados brutos em transparência e eficiência. Como autor e desenvolvedor, acredito na democratização do conhecimento. Essa visão resultou em uma biblioteca de mais de 530 artigos gratuitos, cobrindo desde a base do WebDev e Infraestrutura até os bastidores da indústria de Jogos e IA. No universo de Game Design, sou autor do livro "GDD – O Guia Definitivo" e documento ativamente meus processos através de DevLogs, unindo rigor técnico e criatividade em projetos desenvolvidos com GDevelop 5. Meu compromisso é conectar engenharia de ponta com as reais oportunidades do mercado de tecnologia.