Armazenamento no Navegador
Aula 6 de 6
Web Storage
HTML5 introduziu localStorage e sessionStorage para armazenamento chave-valor no navegador.
// localStorage - persistente entre sessões
localStorage.setItem('tema', 'escuro');
localStorage.setItem('usuario', JSON.stringify({ nome: 'João', id: 1 }));
const tema = localStorage.getItem('tema');
const usuario = JSON.parse(localStorage.getItem('usuario'));
localStorage.removeItem('tema');
localStorage.clear();
// sessionStorage - limpo ao fechar a aba
sessionStorage.setItem('carrinho', JSON.stringify(['item1', 'item2']));
// Storage event (dispara em OUTRAS abas do mesmo domínio)
window.addEventListener('storage', (e) => {
console.log(`Chave "${e.key}" alterada de "${e.oldValue}" para "${e.newValue}"`);
});
// Helper para storage com tipo seguro
function salvarPreferencias(prefs) {
localStorage.setItem('preferencias', JSON.stringify(prefs));
}
function carregarPreferencias() {
try {
return JSON.parse(localStorage.getItem('preferencias')) || {};
} catch {
return {};
}
}
IndexedDB
Banco de dados NoSQL no navegador para dados estruturados e grandes volumes.
// Abrir banco
const request = indexedDB.open('MeuBanco', 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Criar object store
const store = db.createObjectStore('produtos', {
keyPath: 'id',
autoIncrement: true
});
// Criar índices
store.createIndex('nome', 'nome', { unique: false });
store.createIndex('preco', 'preco', { unique: false });
store.createIndex('categoria', ['categoria', 'nome'], { unique: false });
};
request.onsuccess = (event) => {
const db = event.target.result;
console.log('Banco aberto:', db.name);
};
// Inserir dados (transação)
function adicionarProduto(produto) {
const request = indexedDB.open('MeuBanco', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const tx = db.transaction('produtos', 'readwrite');
const store = tx.objectStore('produtos');
store.add(produto);
tx.oncomplete = () => {
console.log('Produto adicionado com sucesso');
db.close();
};
};
}
// Consultar por índice
function buscarPorCategoria(categoria) {
const request = indexedDB.open('MeuBanco', 1);
request.onsuccess = (event) => {
const db = event.target.result;
const tx = db.transaction('produtos', 'readonly');
const store = tx.objectStore('produtos');
const index = store.index('categoria');
const range = IDBKeyRange.only(categoria);
index.getAll(range).onsuccess = (e) => {
console.log('Produtos:', e.target.result);
db.close();
};
};
}
Cache API
Interface programática para cache de requisições HTTP, usada com Service Workers.
// Adicionar ao cache
async function cacheRecurso(url) {
const cache = await caches.open('api-v1');
await cache.add(url);
}
// Cache com requisição customizada
async function cacheComOpcoes(url) {
const cache = await caches.open('api-v1');
const response = await fetch(url, {
headers: { 'X-Cache': 'force' }
});
cache.put(url, response.clone());
return response;
}
// Recuperar do cache
async function getFromCache(url) {
const cache = await caches.open('api-v1');
const response = await cache.match(url);
return response || fetch(url);
}
// Estratégia Stale-While-Revalidate
async function swrStrategy(url) {
const cache = await caches.open('dynamic');
const cached = await cache.match(url);
const fetchPromise = fetch(url).then(response => {
cache.put(url, response.clone());
return response;
});
return cached || fetchPromise;
}
Service Workers
// Registrar Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(reg => console.log('SW registrado:', reg.scope))
.catch(err => console.error('Erro SW:', err));
}
// Verificar atualizações
navigator.serviceWorker.register('/service-worker.js').then(reg => {
reg.addEventListener('updatefound', () => {
const novoSW = reg.installing;
novoSW.addEventListener('statechange', () => {
if (novoSW.state === 'installed' && navigator.serviceWorker.controller) {
console.log('Nova versão disponível! Atualize a página.');
}
});
});
});
PWA Manifest
{
"name": "Meu App PWA",
"short_name": "MeuApp",
"description": "Exemplo de Progressive Web App",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3498db",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
<link rel="manifest" href="/manifest.json">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
Lab: PWA To-Do List
Crie um PWA funcional com service worker, cache offline e manifest. Use IndexedDB para persistência.
# Testar offline
# DevTools > Network > Marcar "Offline"
# Verificar cache
# DevTools > Application > Cache Storage
# Verificar Service Worker
# DevTools > Application > Service Workers
Armazenamento no navegador evoluiu de cookies para um ecossistema completo: Web Storage para sessões, IndexedDB para dados estruturados, Cache API para assets e Service Workers para offline.