HTML5 - Criação de experiências offline com AppCache e IndexedDB HTML5

Israel Hilerio

Gerente principal de programa, Microsoft Internet Explorer

Usuários esperam que seus sites e aplicativos funcionem bem mesmo quando a rede não está disponível. Com dados armazenados cada vez mais na nuvem, desenvolvedores querem possibilitar experiências fluidas que permitam acesso a dados quando não há conectividade; quando dispositivos estão desconectados da rede ou quando encontram pontos cegos na cobertura.

Nesta postagem, mostramos como se criarem sites e aplicativos offline bem comportados usando os recursos HTML5 a seguir:

  • AppCache para armazenar recursos de arquivo localmente e acessá-los offline como URLs
  • IndexedDB para armazenar dados não estruturados localmente para que se possa acessar e consultá-los
  • Armazenamento DOM para pequenas quantidades de informações em texto localmente
  • Eventos offline para detectar se você está conectado à rede

JJ983447.984EB821ABDB168977E12C8FCD1C05E3(pt-br,MSDN.10).png

Exemplo: Suporte offline para acesso em qualquer lugar

Digamos que você vai às compras com a impressão de uma receita de seu site de comidas favorito, mas, quando está no mercado, não consegue encontrar alguns ingredientes importantes.

Imagine que, quando está em casa usando seu computador móvel para navegar pelo site de receitas, uma parte do site foi baixada automaticamente para uso offline. Isso permite que você leve seu computador móvel, acesse o site e procure uma nova receita no mercado. A melhor parte é que você pode fazer isso sem estar conectado a uma rede. Como consumidor, você gostaria ainda mais do site, porque ele simplesmente funcionou quando e onde você precisou.

JJ983447.F30729E3157600F60F7FB99F84D5FACC(pt-br,MSDN.10).png

JJ983447.9070F677E3C83142EDC1F9689FEE3FB0(pt-br,MSDN.10).png

Resultados offline de pesquisa da palavra 'bolo' usando o site de receitas.

Como desenvolvedor, você pode habilitar esses tipos de cenários com uma combinação de tecnologias offline: AppCache, IndexedDB, Armazenamento DOM, e WebSockets (ou XHR). Antes de explorarmos as tecnologias individuais, vejamos os benefícios.

Para aplicativos do estilo Metro e sites, tecnologias offline permitem lidar com falhas de conectividade. Imagine que seus usuários estejam preenchendo um formulário e perca a conectividade de rede. O que seu site ou aplicativo estilo Metro deve fazer? Uma postura de desenvolvimento livre de conexão permite que seu aplicativo trabalhe direito independentemente de estar conectado à rede ou não. Seu aplicativo simplesmente funcionará direito.

Em cenários mais sofisticados, sites e aplicativos permitem que usuários criem novo conteúdo e armazenem dados novos, embora o aplicativo esteja totalmente offline. Imagine o Outlook Web Access (OWA), Hotmail ou o GMail funcionando diretamente quando offline, como o Outlook faz hoje.

Tecnologias offline também pode melhorar o desempenho geral servindo localmente recursos armazenados no cache, armazenando informações futuras previamente no cache e mudando a capacidade de processamento da nuvem (ou da rede) para o dispositivo cliente. Quanto mais informações você puder armazenar em cache localmente, pesquisar localmente, menos recursos do servidor são necessários e mais rápida será a experiência dos usuários.

As expectativas de um aplicativo estilo Metro funcionar offline são mais altas que as de sites trabalhando offline. Como são implantados usando pacotes autônomos do repositório, os usuários esperam que eles tenham algum tipo de funcionalidade offline (por exemplo, jogos, livros, receitas, etc.). Mesmo que esses aplicativos não possam criar ou acessar conteúdo novo, conteúdo anterior deve ficar visível (por exemplo, contatos, reuniões, feeds, revistas, etc.).

Armazene recursos de arquivo em cache localmente usando AppCache

O AppCache permite que você crie caches locais duradouros de recursos de arquivo baixados; recursos que você pode acessar offline ou quando online para melhorar o desempenho. Imagine que uma criança de três anos use um laptop para baixar um jogo interativo da Web (KidsBook) de sua rede doméstica. Se os recursos do aplicativo estiverem armazenados localmente, a criança pode continuar jogando no carro, onde não há conectividade de rede.

Se o KidsBook fosse implementado usando o AppCache, teria armazenado no cache os recursos necessários (JavaScript, HTML, CSS, áudio, vídeo, etc.) para ser jogado quando baixado na primeira vez e depois, quando desconectado da rede. Isso permite à criança continuar entretida, embora o dispositivo em si não tenha conectividade com a rede.

JJ983447.BD843C435F905493F8CD57CD0D26B7BF(pt-br,MSDN.10).png

Fluxo de criação do AppCache.

Para ver como habilitar um jogo interativo da Web para funcionar offline, veja o exemplo do KidsBook no site do test-drive do IE.

O AppCache usa um arquivo de manifesto para especificar URIs de recursos para armazenar conteúdo de um site no cache. O armazenamento no cache acontece nos bastidores depois que o navegador exibe a página da Web, o que permite que recursos definidos no arquivo de manifesto sejam baixados. Isso garante que recursos sejam baixados para a máquina local, como uma unidade em uma única transação, para criar um cache local. Se o download de um único recurso falhar, nenhum cache é criado. Para atualizar o conteúdo armazenado no cache, atualize o arquivo de manifesto em seu servidor. Quando o usuário acessa o site novamente, o navegador compara o arquivo de manifesto no servidor com a última cópia armazenada no cache. Se a cópia do manifesto no cache for diferente da no servidor, uma nova versão do cache é criada usando o conteúdo definido no arquivo de manifesto atualizado.

O AppCache também permite que o Internet Explorer e aplicativos estilo Metro acessem recursos armazenados no cache no modo offline usando URLs tradicionais. Isso permite que você digite uma URL na janela do navegador e acesse essas informações sem nenhuma conectividade de rede. Além disso, páginas offline podem resolver URIs usando as informações armazenadas no cache local. Para amostras de código, dê uma olhada na seção Cache de aplicativos HTML5 (“AppCache”) do Guida do desenvolvedor do IE10.

No geral, o AppCache oferece algumas vantagens sobre o armazenamento em cache do HTTP. O armazenamento em cache HTTP não garante que recursos armazenados ficarão disponíveis depois que os TIF (arquivos temporários de Internet) forem removidos. Além disso, o armazenamento em cache HTTP não resolve URLs corretamente enquanto offline. Contudo, o armazenamento em cache HTTP pode ser usado para otimizar o comportamento do AppCache ao especificar o tempo de vida de um recurso armazenado. Isso determina se um recurso é baixado da Web ou copiado do cache quando uma nova versão de um cache local é criada.

Aplicativos estilo Metro podem beneficiar-se do AppCache armazenando localmente recursos da Web que são acessados por iframes, o que permite que conteúdo seja acessado offline.

Armazene dados estruturados grandes localmente usando IndexedDB

O IndexedDB é um banco de dados local criado para armazenar objetos JavaScript na máquina local, permitindo indexação e pesquisa rápidas de objetos. O site de receitas apresentado anteriormente inclui um banco de dados com dezesseis receitas extraídas de um site-pai. Imagine usar um RSS feed, um WebSocket ou uma conexão XHR para atualizar esse banco de dados periodicamente. Isso permitiria que seus usuários tivessem acesso às últimas receitas, mesmo sem conectividade de rede.

O IndexedDB permite que manipular e indexar objetos JavaScript diretamente. Uma vantagem de se usar o indexedDB para pesquisar informações localmente é que ele reduz os custos de computação ao não forçar você a sempre pesquisar na nuvem Isso pressupõe que você pode manter a relevância dos dados armazenados em cache no sistema local.

JJ983447.BDD42D2A538962B0DE48F2217C050E24(pt-br,MSDN.10).png

JJ983447.9070F677E3C83142EDC1F9689FEE3FB0(pt-br,MSDN.10).png

Exibe uma lista de receitas armazenadas na máquina local acessíveis via IndexedDB.

O IndexedDB é uma tecnologia criada em torno de conceitos de banco de dados de ISAM. Como muitas tecnologias de plataforma Web, ele é criado para fornecer uma API de baixo nível que pode ser usada por várias abstrações de biblioteca criadas sobre ele A tabela a seguir comprar conceitos de desenvolvimento do IndexedDB com conceitos similares do Modelo relacional bem entendido.

Conversion Error: Invalid style applied inside cellConversion Error: Invalid style applied inside cellConversion Error: Invalid style applied inside cell

Banco de dados

Banco de dados

Banco de dados

Tabelas

Tabelas contêm colunas e linhas

O objectStore contém objetos e chaves Javascript

Mecanismo de consulta, associação e filtros

SQL

APIs de cursos, APIs de faixa de chave e código de aplicativo

Tipos e bloqueios de transação

O bloqueio pode acontecer em bancos de dados, tabelas ou linhas em transações READ_WRITE

O bloqueio pode acontecer no banco de dados em transações VERSION_CHANGE, em um objectStores em transações READ_ONLY e READ_WRITE. Não existe bloqueio no nível de objeto

Confirmações de transação

A criação de transação é explicita. O padrão é reverter a menos que eu invoque confirmação

A criação de transação é explicita. O padrão é confirmar a menos que eu invoque anular ou haja uma exceção não detectada

Pesquisas de propriedade

SQL

Índices são necessários para consultar propriedades de objeto diretamente

Registros/dados

Forma normal e propriedades de valor único

Forma não normalizada e pode ter propriedades de valores múltiplos

Quando usa o IndexedDB, você cria bancos de dados que contêm repositórios de objetos (contatos, emails, reuniões, etc.). Esses repositórios contêm os objetos JavaScript necessários para o seu aplicativo (Contatos – primeiro nome, sobrenome, endereço, etc.). Espera-se que cada objeto JavaScript tenha um identificador exclusivo acessível através de um keyPath. Além disso, repositórios de objetos contêm índices em propriedades que podem ser usados para consultar o conjunto de dados (Emails – assuntos, datas, etc.). Filtros são usados para organizar ou reduzir o conjunto de resultados via KeyRanges em índices ou no repositório de objetos.

O trecho de código a seguir mostra como ler um registro de livro de um banco de dados "Biblioteca":

var oRequestDB = window.indexedDB.open("Library");
oRequestDB.onsuccess = function (event) {
db1 = oRequestDB.result;
if (db1.version == 1) {
txn = db1.transaction(["Books"], IDBTransaction.READ_ONLY);
var objStoreReq = txn.objectStore("Books");
var request = objStoreReq.get("Book0");
request.onsuccess = processGet;
}
};

Informações contidas em repositórios de objetos são sempre acessadas para leitura ou gravação no contexto de uma transação. Existem três tipos de transações:

  • VERSION_CHANGE – usada para criar ou atualizar repositório de objetos e índices. Como transações VERSION_CHANGE bloqueiam o banco de dados completo e impedem operações simultâneas, não são recomendadas para a gravação de dados no banco de dados.
  • READ_WRITE – permite que registros contidos em repositórios de objetos sejam adicionados, lidos, modificados e excluídos.
  • READ_ONLY – permite que registros contidos em repositórios de objetos sejam lidos.

O modelo de API assíncrono fornecido pelo IndexedDB potencializa o modelo de solicitação/resposta suportado por muitas APIs da Web, como a XHR. Solicitações são enviadas ao processo IndexedDB local e os resultados são tratados pelos manipuladores de eventos onsuccess ou onerror do cliente. Além disso, não há mecanismo explícito para confirmar uma transação. Transações são confirmadas quando não há solicitações pendentes no servidor e nenhum resultado pendente no cliente. Além do mais, cabe ao seu aplicativo tratar de exceções e de eventos de erro. Em muitos casos, se uma exceção ou erro não for tratado, a transação é anulada.

Resumindo, o IndexedDB é um mecanismo otimizado para a consulta de objetos de dados via índices. Ele dá a sites as APIs para acessarem grandes quantidades de dados relacionados via cursores e para filtrarem dados usando objetos KeyRange. O padrão que acreditamos que os desenvolvedores seguirão é ter um banco de dados "mestre" com todos os registros de usuários residindo na nuvem e um banco de dados IndexedDB local com um subconjunto de registros para facilitar pesquisas rápidas e acesso a dados offline.

Armazene dados textuais pequenos localmente com armazenamento DOM e eventos offline/online

Sites podem usar armazenamento DOM e eventos de conectividade para lidar com pequenas quantidades de dados textuais e detectar conectividade ruim. Imagine um jogo que use essas tecnologias para acompanhar o placar do jogador enquanto offline. Imagine o que aconteceria se você tivesse uma pontuação alta quando houvesse perda de conectividade. A página da Web pararia ou travaria?

Como esses dados são de natureza textual e não precisam de muito espaço, você pode usar armazenamento DOM para armazenar as informações localmente, sem a necessidade de conectividade de rede, e fazer o upload deles posteriormente quando a rede estiver disponível. O armazenamento DOM suporta mais dados que cookies e não precisa de codificação de dados. Além disso, o armazenamento DOM não envia dados ao servidor em cada solicitação e pode ser definido para acesso a domínio ou sessões.

JJ983447.491282E767B6337CE516BC585871BB8F(pt-br,MSDN.10).png

Usar essa tecnologia é tão simples quanto acessar o objeto windows.localStorage. Nesse objeto, você pode verificar ou adicionar pares nome/valor na forma de propriedades. O trecho de código a seguir mostra como armazenar o placar do jogo localmente usando localStorage:

<script type="text/javascript">
var lStorage;
 
function init() {
if (window.localStorage) {
lStorage = window.localStorage;
 
if (typeof lStorage.score == 'undefined')
lStorage.score = 0;
 
document.getElementById('score').innerHTML = lStorage.score;
}
}
 
function save() {
if (lStorage) {
lStorage.score = getGameScore();
}
}
</script>
...
<body onload="init();">
<p>
Your last score was: <span id="score">last score insert in init()</span>
</p>
</body>

Além disso, os eventos offline/online ajudarão você quando tiver acesso a rede para que possa enviar os dados a seu servidor. Por exemplo, você pode detectar quando está online e atualizar o banco de dados com conteúdo do servidor usando WebSockets ou XHR.

Isso é simples como verificar o estado da propriedade navigator.onLine. O código a seguir mostra como registrar-se para eventos online e offline:

function reportConnectionEvent(e) {
if (!e) e = window.event;
if ('online' == e.type) {
alert('The browser is ONLINE.');
}
else if ('offline' == e.type) {
alert('The browser is OFFLINE.');
}
}
 
window.onload = function () {
status = navigator.onLine; //retrieve connectivity status
document.body.ononline = reportConnectionEvent;
document.body.onoffline = reportConnectionEvent;
}

Em aplicativos estilo Metro, fornecemos uma API adicional, Windows.ApplicationData, que permite armazenar mais tipos de dados localmente e que eles se desloquem entre várias máquinas.

O ponto principal é criar o aplicativo ou site com a ideia de que sua conectividade pode desaparecer a qualquer momento e que você precisa poder lidar com essa situação de forma suave. Implementar um padrão de dados que armazene informações localmente antes de enviá-las para a nuvem ajudará você a lidar com conexões de rede problemáticas.

Atualize dados locais com WebSockets e XHR

Para alguns cenários, os dados de seu cliente continuarão a viver na nuvem para serem facilmente acessíveis de qualquer dispositivo. Portanto, você precisa garantir que os dados armazenados em cache permaneçam relevantes e atuais. Para isso, você precisa criar canais para sincronizar dados entre a nuvem e seu aplicativo. Você pode potencializar WebSockets e XHR para facilitar essa sincronização. Isso requer que você empacote seus dados em formatos transferíveis (por exemplo, XML ou JSON), use XHR ou Websockets para transferir aqueles recursos para o cliente e depois use analisadores XML ou JSON para criar objetos JavaScript que serão armazenados no banco de dados IndexedDB. Isso também pode ser usado para se carregarem no servidor informações armazenadas no armazenamento DOM.

Conclusão

A conectividade de rede nem sempre é confiável; entretanto, seus aplicativos precisam ser. Usar essas tecnologias offline para antecipar escassez de rede tornará seus aplicativos ainda melhores em muitos cenários de cliente e situações. Além disso, você pode tirar proveito de uma grande oportunidade de diferenciar seu site e aplicativos estilo Metro permitindo que eles funcionem offline. Isso aumentará a utilização deles e criará uma oportunidade maior para o seu serviço. Potencialize as várias tecnologias offline especificadas aqui (AppCache, IndexedDB, armazenamento DOM e outras) para armazenar em cache o máximo de informações possíveis localmente.

Para mais informações, veja a apresentação do BUILD Criação de acesso offline em aplicativos estilo Metro e sites usando HTML5, que também descreve a função da API de arquivo para lidar com cenários offliine.

Mostrar: