O documento discute as soluções HTML5 para aplicações offline e armazenamento de dados, incluindo AppCache para armazenar recursos offline, Local Storage e Session Storage para armazenamento de dados não estruturados no cliente, e Indexed DB para armazenamento de dados estruturados. O documento fornece exemplos de código para demonstrar como usar essas APIs do HTML5 para permitir que aplicações funcionem offline e armazenem dados localmente no navegador.
21. OFFLINE ...
Armazenamento de
recursos no cliente
Permite obtê-los sem
conexão
Hybrid Apps & Mobile
UIWebView (iOS)
WebView (Android)
22. ... & STORAGE
Evita full HTTP
roundtrips
Menor consumo de
banda
STANDALONE* Hybrid
Apps & Mobile
23. HTML5 AppCache
Define recursos que DEVEM ser armazenados em
cache
Define recursos que NÃO DEVEM ser armazenados em
cache
Definição de recursos alternativos
24. AppCache Manifest
Arquivo “plain text”
Começa com CACHE MANIFEST
Os recursos podem ser declarados diretamente na
“raiz” ou em um grupo CACHE
Adicione um comentário para versionamento e controle
de expiração
25. AppCache Manifest
offline.appcache
CACHE MANIFEST
# Version 1
CACHE:
# Todas as páginas aqui, por favor
img/logo.png
css/index.css
js/index.js
js/cachecontrol.js
# Cache de recursos distribuidos (CDN)
http://code.jquery.com/jquery.min.js
http://yui.yahooapis.com/combo?3.6.0/build/cssfonts/cssfonts-min.css&3.6.0/build...
26. AppCache Manifest
Cache de recursos distribuidos
Tem parâmetros na URL?
Não funcionará.
Encontre ou crie URLs sem parâmetro e tudo vai ficar
bem
27. AppCache Manifest
offline.appcache
CACHE MANIFEST
# Version 1
CACHE:
# Todas as páginas aqui, por favor
img/logo.png
css/index.css
js/index.js
# Cache de recursos distribuidos (CDN)
http://code.jquery.com/jquery.min.js
http://yui.yahooapis.com/3.6.0/build/cssreset/cssreset-min.css
http://yui.yahooapis.com/3.6.0/build/cssfonts/cssfonts-min.css
http://yui.yahooapis.com/3.6.0/build/cssbase/cssbase-min.css
28. AppCache Manifest
Tem algum recurso que NÃO deve ser cacheado?
Você pode definir recursos ou “prefixos” que não
devem ser adicionados o AppCache
Com conexão, o navegador tentará obter o recurso da
maneira tradicional
Declare em um grupo NETWORK
29. AppCache Manifest
offline.appcache
CACHE MANIFEST
# Version 1
CACHE:
# ...
# Ainda está tudo aqui :)
NETWORK:
# A ‘/’ no fim do caminho serve como ‘/*’ (wildcard)
realtime/
api/
live/chat.php
utils/sendmail.aspx
30. AppCache Manifest
Feedback sobre o que não pode ser acessado offline
Declare recursos alternativos em um grupo FALLBACK:
Qualquer recurso (HTML, CSS, JavaScript) pode ter
uma versão alternativa
Qualquer “prefixo” pode apontar para um recurso
alternativo
31. AppCache Manifest
offline.appcache
CACHE MANIFEST
# Version 1
CACHE:
# ...
# Ainda está tudo aqui :)
NETWORK:
# ...
# Ainda está tudo aqui :)
FALLBACK:
chat.jsp offline.html
img/top.jpg img/offline_badge_top.jpg
events/ notconnected.html
http://www.facebook.com/plugins/ notconnected.html
http://platform.twitter.com/ notconnected.html
32. AppCache - Utilização
Configure seu servidor para responder o manifesto
com MIME text/cache-manifest - *.appcache
Adicione o atributo “manifest” em todos os HTMLs que
devem estar disponíveis offline
Cuidado: algum recurso respondeu 404?
Nada vai para o cache!
34. AppCache
Server
A C E M*
B D F
Client (browser)
35. AppCache
A C
B D
Server
A C E M*
B D F M*
Client (browser)
36. AppCache
A C
B D
HTTP cache
A C E
B D F
A C
App Cache
B D
Server
A C E M*
B D F M*
Client (browser)
37. AppCache
A C
B D
HTTP cache
A C E
B D F
App Cache
Server
A C E M*
B D F M*
Client (browser)
38. AppCache
A C
B D
HTTP cache
A E C
B F D
A E
App Cache
B F
Server
A C E M*
B D F M*
Client (browser)
39. AppCache - Expiração
Mudou uma imagem? Incremente o número de versão
no comentário
Detecte alterações no AppCache Manifest e reconstrua
o cache
Faça isso com JavaScript
Assegure-se de recarregar a página para obter os
novos recursos
40. AppCache - Expiração
js/cachecontrol.js
window.applicationCache.addEventListener(‘updateready’, function(event) {
if(window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Um novo manifesto foi detectado, vamos pegar os recursos de novo:
window.applicationCache.swapCache();
// Já temos os novos recursos. Vamos mostrá-los:
if(confirm(‘Nova versão online. Deseja carregar agora?’)) {
window.location.reload();
} else {
// Merece uma mensagem avisando que a versão é obsoleta, não acham?
}
}
}, false);
41. AppCache - Expiração
Cuidado: impeça que o navegador adicione o
AppCache Manifesto ao HTTP Cache!
“access plus 0 seconds”
42. Online & Offline Events
Agumas coisas só devem funcionar com uma conexão
ativa. E se a conexão cair?
A mudança de status na atividade da conexão deve
disparar um evento no navegador
Podemos capturar esse evento com JavaScript
43. Online & Offline Events
js/cachecontrol.js
// Aquele código ainda está por aqui :)
window.addEventListener(‘offline’ function(event) {
// Event Listeners impedindo novos requests
// salvaremos tudo localmente
}, false);
window.addEventListener(‘online’ function(event) {
// Enviar o que está no armazenamento local para o servidor. SYNC!
// Remover Event Listeners e deixar novos requests serem feitos
}, false);
45. Local Storage
É como um cookie, só que melhor
Para guardar dados não-estruturados
“Same origin”
http://exemplo.com:80 ≠ http://exemplo.com:8080
46. Local Storage
js/cachecontrol.js
// Aquele código ainda está por aqui :)
// salvaremos tudo localmente COM LOCAL STORAGE
// Só podemos salvar Strings (DOMString)
localStorage.setItem(‘userId’, ‘77634810’);
// Mas isso é uma String não?
localStorage.setItem(‘newContractFormData20120605091422’, JSON.stringify({
email : ‘bla@foo.com’,
company: ‘Foo Enterprises LLC’,
createdAt: ‘2012-6-5 09:14:22’
}));
47. Local Storage - API
.setItem ( key, value );
.getItem( key );
.removeItem( key );
.clear( );
48. Local Storage
Use .clear( ) e .removeItem( key ) somente se
necessário
Usuário pode descartar dados armazenados pelas
configurações do navegador (limpar dados de
aplicações)
49. Session Storage
Idêntico ao Local Storage, só que persiste por uma
“sessão”
Fechou a janela, acabou
Fechou a aba, acabou (*)
50. Indexed DB
Feito para armazenar dados estruturados (object store)
Assíncrono e transacional
“Full-featured document based schemaless NoSQL”
51. Indexed DB - Utilização
Criaremos a “base”
Criaremos um “Object Store” na “base”
52. Indexed DB - Utilização
js/cachecontrol.js
// Aquele código ainda está por aqui :)
var idb = {};
idb.db = null;
idb.open = function() {
var idbDatabase = indexedDB.open(‘caelum’, ‘Indexed DB Caelum Online’);
idbDatabase.onsuccess = function(event) {
idb.db = event.target.result;
var v = ‘1.0’;
if (v != idb.db.version) {
var setVersionTransaction = idb.db.setVersion(v);
setVersionTransaction.onsuccess = function(event) {
var store = idb.db.createObjectStore(‘comentarios’, { keyPath: ‘createdAt’});
}
}
};
};
53. Indexed DB - Utilização
Abriremos a base
Vamos inserer um objeto no Object Store
54. Indexed DB - Utilização
js/cachecontrol.js
// Aquele código ainda está por aqui :)
idb.createComentario = function(comentario) {
var transaction = idb.db.transaction([‘caelum’], IDBTransaction.READ_WRITE, 0);
var store = transaction.objectStore(‘comentarios’);
var commit = store.put({
content : comentario,
createdAt : new Date().getTime()
});
commit.onsuccess = function(event) {
// callback
}
};
55. Indexed DB - Utilizção
Vamos fazer um “SELECT *”, mas usando um cursor
56. Indexed DB - Utilização
js/cachecontrol.js
// Aquele código ainda está por aqui :)
idb.getComentarios = function() {
var transaction = idb.db.transaction([‘caelum’], IDBTransaction.READ_WRITE, 0);
var store = transaction.objectStore(‘comentarios’);
var keyRange = IDBKeyRange.lowerBound(0);
var cursor = store.openCursos(keyRange);
cursor.onsuccess = function(event) {
var current = e.target.result;
// Paramos o cursor com Explicit Boolean Comparison
// para evitar outros valores válidos
if(!!current == false) {
return;
}
// callback
};
};
57. E quando a conexão voltar?
Mande os dados nos callbacks por XHR, por exemplo
Cuidado: leitura assíncrona, requisições XHR,
callbacks, você sabe onde isso vai parar se não souber
muito bem o que está fazendo...
58. Perguntas? Eu tenho...
Quanto posso armazenar?
App Cache Indeterminado
Local Storage 5MB mínimo
Session Storage 5MB mínimo
Indexed DB Indeterminado
59. Perguntas? Eu tenho...
Funciona em que navegador?
Internet
Chrome Firefox Opera Safari
Explorer
App
4 3.5 10 10.60 4
Cache
Local
4 3.5 8 10.50 4
Storage
Session
5 2 8 10.50 4
Storage
Indexed
12 16 10 -- --
DB
60. Perguntas? Eu tenho...
Mas você citou “MOBILE”
Android
iOS (Safari) Opera Mini
Browser
App Cache 3.2 -- 2.1
Local Storage 3.2 -- 2.1
Session
3.2 -- 2.1
Storage
Indexed DB -- * -- ? -- *
Mesmo tendo sido visitado antes, com recursos no cache do navegador, a inexistência da conexão impede a exibição da página\n
\n
\n
\n
\n
\n
\n
\n
Mesmo com recursos em cache é impossível obtê-los para exibição, é preciso uma conexão ativa para que o navegador faça a requisição e só então o navegador verifica se o recurso armazenado está em cache para utilizá-lo\n
Quando imaginamos a WWW como a plataforma de aplicações ENTERPRISE do futuro, temos que contornar essa situação de alguma maneira\nAté aplicações desktop client/server sofrem com isso: “Desculpa senhor, estamos sem sistema”\n
Viagens, conexões ruins, blind spots\nApps que devem carregar uma página mesmo sem conexão\n
Armazenamento local\n
\n
\n
Declare todos as páginas no manifesto, assim toda sua app é cacheada a partir da home\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
Mesmo com o cache atualizado, a aplicação ainda utilizará o cache antigo se não chamarmos swapCache\n
\n
\n
\n
\n
Cookie 4095 bytes, enviado em todas requisições\nlocalStorage no mínimo 5MB, não é enviado\n
Foi feito para salvar Strings, mas podemos abusar do JSON Parsing\n
\n
\n
Não é consistente até mesmo em um mesmo navegador\n
\n
\n
indexedDB.open(nome, descrição), onsuccess para usar a base\nObject Store +- tabela\nPrecisa mudar a versão do idb para criar uma\n
\n
indexedDB.open(nome, descrição), onsuccess para usar a base\nObject Store +- tabela\nPrecisa mudar a versão do idb para criar uma\n
\n
\n
\n
App Cache pode ser limitado a 10% do espaço em disco disponível\nIndexed DB é indeterminado por definição\n
\n
Você pode usar UIWebView / WebView e armazenar no device? WebSQL?\n