Web Storage em JavaScript: localStorage, sessionStorage e IndexedDB
A persistência de dados no navegador é fundamental para criar aplicações web modernas. Web Storage oferece três mecanismos distintos, cada um com propósitos específicos. Dominar essas tecnologias permite que você construa experiências offline, melhore performance e gerencie estado de forma eficiente.
localStorage: Armazenamento Persistente
O localStorage mantém dados indefinidamente no navegador do usuário, mesmo após fechar a aba ou reiniciar o computador. Funciona como um dicionário chave-valor simples, perfeito para preferências do usuário, temas, tokens de autenticação e configurações.
Operações Básicas
// Salvar dados
localStorage.setItem('usuario', 'João Silva');
localStorage.setItem('tema', 'escuro');
// Recuperar dados
const usuario = localStorage.getItem('usuario');
console.log(usuario); // 'João Silva'
// Remover item específico
localStorage.removeItem('tema');
// Limpar todo o localStorage
localStorage.clear();
// Verificar quantidade de itens
console.log(localStorage.length);
Trabalhando com Objetos
Como localStorage só armazena strings, você precisa serializar objetos com JSON:
const usuario = {
id: 1,
nome: 'Maria',
email: 'maria@email.com',
preferencias: {
notificacoes: true,
idioma: 'pt-BR'
}
};
// Salvar objeto
localStorage.setItem('userData', JSON.stringify(usuario));
// Recuperar e desserializar
const dadosRecuperados = JSON.parse(localStorage.getItem('userData'));
console.log(dadosRecuperados.preferencias.idioma); // 'pt-BR'
// Deletar se não existir erro
if (dadosRecuperados) {
console.log('Dados encontrados');
}
Limite e Considerações
localStorage oferece tipicamente 5-10MB de espaço. Use para dados que precisam persistir entre sessões, mas evite armazenar senhas ou informações sensíveis sem criptografia.
sessionStorage: Armazenamento Temporário
O sessionStorage funciona identicamente ao localStorage, mas os dados são descartados quando a aba do navegador fecha. Ideal para dados temporários da sessão atual, como filtros de busca, estado de formulários em progresso ou tokens de sessão curta.
Diferenças Práticas
// Salvar dados de sessão
sessionStorage.setItem('filtroAtivo', 'ultimas24h');
sessionStorage.setItem('carrinhoTemp', JSON.stringify({
items: ['produto1', 'produto2'],
timestamp: Date.now()
}));
// Recuperar dados
const filtro = sessionStorage.getItem('filtroAtivo');
const carrinho = JSON.parse(sessionStorage.getItem('carrinhoTemp'));
// Dados desaparecem ao fechar a aba
sessionStorage.clear();
O sessionStorage é isolado por aba: diferentes abas do mesmo site têm seus próprios espaços de armazenamento. Aproveite isso para fluxos independentes.
IndexedDB: Armazenamento Estruturado em Grande Escala
IndexedDB é um banco de dados NoSQL do navegador, oferecendo capacidade muito maior (centenas de MB), suporte a índices, transações e consultas complexas. Use para aplicações offline robustas, sincronização de dados e armazenamento estruturado.
Criação e Configuração Inicial
let db;
// Abrir ou criar banco de dados
const request = indexedDB.open('minhaApp', 1);
request.onerror = () => console.error('Erro ao abrir banco');
request.onsuccess = (event) => {
db = event.target.result;
console.log('Banco aberto com sucesso');
};
// Evento acionado apenas na primeira vez ou ao atualizar versão
request.onupgradeneeded = (event) => {
db = event.target.result;
// Criar object store (tabela)
if (!db.objectStoreNames.contains('usuarios')) {
const objectStore = db.createObjectStore('usuarios', { keyPath: 'id' });
objectStore.createIndex('email', 'email', { unique: true });
objectStore.createIndex('nome', 'nome', { unique: false });
}
};
Inserir, Ler e Atualizar Dados
// Inserir/atualizar documento
function salvarUsuario(usuario) {
const transaction = db.transaction(['usuarios'], 'readwrite');
const objectStore = transaction.objectStore('usuarios');
const request = objectStore.put(usuario);
request.onsuccess = () => console.log('Usuário salvo');
request.onerror = () => console.error('Erro ao salvar');
}
// Recuperar por chave primária
function buscarUsuario(id) {
const transaction = db.transaction(['usuarios'], 'readonly');
const objectStore = transaction.objectStore('usuarios');
const request = objectStore.get(id);
request.onsuccess = (event) => {
console.log('Usuário:', event.target.result);
};
}
// Buscar por índice
function buscarPorEmail(email) {
const transaction = db.transaction(['usuarios'], 'readonly');
const objectStore = transaction.objectStore('usuarios');
const index = objectStore.index('email');
const request = index.get(email);
request.onsuccess = (event) => {
console.log('Encontrado:', event.target.result);
};
}
// Deletar
function deletarUsuario(id) {
const transaction = db.transaction(['usuarios'], 'readwrite');
const objectStore = transaction.objectStore('usuarios');
const request = objectStore.delete(id);
request.onsuccess = () => console.log('Deletado');
}
// Exemplo de uso
salvarUsuario({
id: 1,
nome: 'Ana Silva',
email: 'ana@email.com',
criado: new Date()
});
Consultas Avançadas
// Listar todos os registros
function listarTodos() {
const transaction = db.transaction(['usuarios'], 'readonly');
const objectStore = transaction.objectStore('usuarios');
const request = objectStore.getAll();
request.onsuccess = (event) => {
console.log('Todos os usuários:', event.target.result);
};
}
// Usar cursor para iteração eficiente
function iterarComCursor() {
const transaction = db.transaction(['usuarios'], 'readonly');
const objectStore = transaction.objectStore('usuarios');
const request = objectStore.openCursor();
request.onsuccess = (event) => {
const cursor = event.target.result;
if (cursor) {
console.log('ID:', cursor.key, 'Dados:', cursor.value);
cursor.continue();
}
};
}
Escolhendo a Tecnologia Correta
| Tecnologia | Limite | Persistência | Melhor Para |
|---|---|---|---|
| localStorage | 5-10MB | Indefinida | Preferências, tokens, configurações |
| sessionStorage | 5-10MB | Fim da sessão | Estado temporário, filtros |
| IndexedDB | 100s MB+ | Indefinida | Apps offline, grandes datasets |
Use localStorage para preferências do usuário, sessionStorage para dados de sessão atual e IndexedDB quando precisar de capacidade, estrutura ou consultas complexas. Para aplicações offline-first, considere combinar IndexedDB com Service Workers para sincronização automática.
Conclusão
Dominando Web Storage, você pode: (1) Construir aplicações que funcionam offline e sincronizam quando conexão retorna; (2) Melhorar performance ao evitar requisições desnecessárias; (3) Criar experiências personalizadas e responsivas mantendo preferências do usuário. Escolha a ferramenta certa conforme a escala e persistência necessárias — localStorage para simples, sessionStorage para temporário, IndexedDB para complexo.