Peter Mbanugoé um desenvolvedor de software com experiência em trabalhar com a pilha Microsoft .NET. Ele é apaixonado pela criação de software de qualidade, com área de interesse em aplicativos off-line e arquitetura de software.
Off-line primeiro é uma abordagem para o desenvolvimento de software diferente da abordagem tradicional, em que a falta de conexão de rede é tratada como um erro, afetando, assim, a experiência geral do usuário. Com a abordagem offline-first, você começa com o ambiente mais restrito e, posteriormente, responde à experiência do usuário do seu aplicativo, aprimorando-o progressivamente à medida que as funcionalidades se tornam disponíveis. Para o offline-first, presume-se que a falta de conexão de rede crie uma experiência de usuário insatisfatória; portanto, o offline-first procura fornecer a melhor experiência de usuário possível em todas as condições.
A abordagem off-line em primeiro lugar traz algumas preocupações, como, por exemplo, como armazenar dados ou gerenciar transações quando off-line e sincronizá-los com o servidor, como manter os dados off-line seguros ou como resolver conflitos de dados se dois usuários fizerem alterações no mesmo registro enquanto estiverem off-line etc. Nesta postagem, analisaremos o armazenamento e a sincronização de dados off-line criando um aplicativo de agenda telefônica na Web para armazenar contatos.
Criar o aplicativo de amostra
Nosso aplicativo de amostra será um aplicativo da Web criado com Bootstrap, jQuery, PouchDB e Couchbase Sync Gateway. Para começar, vamos criar o layout da página, que incluirá um formulário para inserir o nome, o e-mail e o telefone do contato e também exibirá uma lista de contatos salvos.
Layout da página
Crie uma pasta para o aplicativo e, em seguida, faça o download bootstrap e jQuery. Descompacte os arquivos e coloque-os em uma nova pasta chamada ativo. Adicione um novo arquivo chamado index.html para sua pasta raiz e copie o trecho abaixo para ela.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
!DOCTYPE html> <html lang="en"> <head> <meta conjunto de caracteres="utf-8"> <link rel="folha de estilo" href="assets/bootstrap/bootstrap.min.css"> </head> <body> <nav classe="navbar navbar-default"> <div classe="contêiner-fluido"> <div classe="navbar-header" (cabeçalho da barra de navegação)> <a classe="navbar-brand" href="#"> Lista telefônica</a> </div> </div> <div classe="contêiner"> <div classe="row" (linha)> <div classe="col-md-10"> <h2>Adicionar novo contato </h2> <hr /> <form id="contactForm" classe="form-horizontal"> <div classe="form-group" (grupo de formulários)> <label para="name" (nome) classe="col-sm-2 control-label">Nome <div classe="col-sm-10"> <input tipo="texto" classe="form-control" (controle de formulário) id="name" (nome) espaço reservado="Nome"> </div> </div> <div classe="form-group" (grupo de formulários)> <label para="móvel" classe="col-sm-2 control-label">Celular <div classe="col-sm-10"> <input tipo="texto" classe="form-control" (controle de formulário) id="móvel" espaço reservado="Móvel"> </div> </div> <div classe="form-group" (grupo de formulários)> <label para="email" classe="col-sm-2 control-label">E-mail <div classe="col-sm-10"> <input tipo="email" classe="form-control" (controle de formulário) id="email" espaço reservado="E-mail"> </div> </div> <div classe="form-group" (grupo de formulários)> <div classe="col-sm-offset-2 col-sm-10"> <button tipo="submit" (enviar) classe="btn btn-default">Salvar contato </div> </div> </form> <hr /> </div> </div> <div classe="row" (linha)> <div classe="col-md-10"> <h2>Lista de contatos</h2> <hr /> <tabela id="contactList" classe="table table-bordered"> <thead> <tr> <th>Nome</th> <th>Celular</th> <th>E-mail</th> <th></th> </tr> </thead> <tbody> </tbody> </table> </div> </div> <script src="assets/jquery-2.1.0.min.js"></script> <script src="assets/bootstrap/bootstrap.min.js"></script> </body> </html> |
O que temos é uma página com um formulário para inserir e salvar contatos e também exibir a lista de contatos salvos
Acesso/armazenamento de dados off-line
Os dados se tornam uma das principais preocupações de um aplicativo Offline-First. Qualquer aplicativo que funcione off-line precisa lidar com o acesso e o armazenamento de dados off-line, que serão tratados por meio do armazenamento de dados no cliente e do tratamento do problema de sincronização de dados de forma confiável. Há vários bancos de dados no lado do cliente para aplicativos móveis e da Web, incluindo o Couchbase Lite e o Cloudant Sync para clientes móveis e de desktop, e o IndexedDB e o Web SQL para navegadores. Para o nosso exemplo, usaremos o PouchDB, uma API de banco de dados do lado do cliente JavaScript modelada com base na API do CouchDB. O PouchDB abstrai os diferentes bancos de dados compatíveis com navegadores e suas diferentes interfaces de programação. Ele foi criado para ajudar a criar aplicativos que funcionem tão bem off-line quanto on-line, armazenando dados localmente enquanto estiverem off-line e sincronizando-os com o servidor e outros clientes conectados quando estiverem on-line.
Também usarei cliente da loja de moletonsum plug-in do PouchDB para persistência de dados e sincronização off-line. Prefiro trabalhar com essa biblioteca por causa da API disponível para trabalhar com dados e sincronização. Ela adiciona automaticamente registros de data e hora quando adiciono novos dados. Adicionarei esse plug-in e o PouchDB usando o npm com o seguinte comando ou farei o download a partir deste cliente da loja & BolsaBD. Observe que estou usando o PouchDB 6.1.2 e o hoodie-store-client 7.0.1.
|
1 2 3 |
npm instalar --salvar bolsadb npm instalar --salvar @moletom com capuz/loja-cliente |
Agora, inclua esses arquivos na página.
|
1 2 |
Com isso feito, adicionamos um novo arquivo chamado index.js no ativo e adicionar um link para esse arquivo na página. Dentro desse arquivo, a primeira coisa que fazemos é inicializar um objeto Store com o nome do banco de dados e a URL do servidor para sincronização.
|
1 2 3 |
$(função(){ var loja = novo Loja('exemplo', { remoto: 'http://localhost:4984/example', PouchDB: PouchDB }); }); |
Adicione o código a seguir para salvar o valor inserido no formulário e também adicioná-lo à lista de contatos da página.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$('#contactForm').enviar(função(evento) { evento.preventDefault(); var nome = $('#name').val(); var e-mail = $('#email').val(); var móvel = $('#mobile').val(); // Salvar o contato no banco de dados loja.adicionar({ nome: nome, móvel: móvel, e-mail: e-mail }); $('#contactForm')[0].redefinir(); }); //adicionar novo contato à página função addNewContactToList(contato) { var novo contato = '' + contato.nome + '' + contato.móvel + '' + contato.e-mail + ' |
' $("#contactList tbody").append(newContact); } //quando uma nova entrada for adicionada ao banco de dados, execute a função correspondente store.on('add', addNewContactToList); function loadContacts() { store.findAll().then(function(contacts) { var tbody = "; $.each(contacts, function (i, contact) { var row = '
|
1 2 |
' + contact.name + '' + contact.mobile + '' + contact.email + ' |
'; tbody += row; }); $("#contactList tbody").html(").html(tbody); }); } // quando o site é carregado no navegador, // carregamos todos os contatos salvos anteriormente do hoodie loadContacts();
|
1 |
Eu usei store.add para inserir no banco de dados local e, em seguida, ouvir os eventos usando store.onparticularmente o adicionar e isso será útil quando começarmos a sincronizar os dados e exibiremos novos dados após uma sincronização completa com bancos de dados remotos. Também adicionei uma função para exibir dados locais quando a página for carregada ou atualizada. Podemos verificar se é possível salvar dados localmente.
Agora temos acesso/armazenamento de dados off-line funcionando. Com o que fizemos até agora, você deve começar a ver a mudança na mentalidade ou no processo de pensamento. Isso significa armazenar dados localmente primeiro e, depois, enviar as alterações para o servidor quando estiver on-line. Nossa próxima etapa é fazer com que ele sincronize esses dados com um servidor Couchbase. Para que isso funcione, precisamos do Couchbase Sync Gateway.
Gateway de sincronização
O Sync Gateway é um aplicativo de gateway da Web seguro com APIs de sincronização, REST, fluxo, lote e evento para acessar e sincronizar dados pela Web. O Sync Gateway permite, entre outras coisas, a replicação segura de dados entre o Couchbase Server e o
Couchbase Lite e/ou PouchDB. Para obter um guia rápido sobre a instalação, consulte este guia. Se o Sync Gateway estiver instalado, ele poderá ser acessado a partir da seção http://localhost:4984 quando iniciado. Se você se lembra, tivemos um url semelhante ao inicializar o Loja para usar o PouchDB, mas com um objeto /exemplo anexado a ele. O apêndice extra especifica o nome do banco de dados com o qual sincronizamos. Para que nosso aplicativo use o armazenamento e a sincronização de dados off-line, vamos iniciar o serviço Sync Gateway e atualizar o JavaScript da página para sincronização automática. Usarei a definição de configuração do Sync Gateway.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
{ "log":["*"], "bancos de dados": { "exemplo": { "servidor":"walrus:", "usuários": { "CONVIDADO": { "desativado": falso, "admin_channels": ["*"] } } } }, "CORS": { "Origem": ["http://127.0.0.1:8801"], "LoginOrigin": ["http://127.0.0.1:8801"], "Headers" (Cabeçalhos): ["Content-Type"], "MaxAge": 17280000 } } |
Temos uma configuração básica que estabelecerá uma conexão com o banco de dados de exemplo e usará a opção de armazenamento na memória (walrus), que, na produção, devemos alterar para apontar para um servidor Couchbase. Também adicionamos uma configuração para permitir o compartilhamento de recursos entre origens para nosso aplicativo, que está em uma porta diferente. Agora temos que iniciar o serviço Sync Gateway executando o seguinte comando no terminal
$ ./bin/sync_gateway my-config/phonebook-config.json
Com o Sync Gateway iniciado, precisamos atualizar o código para a sincronização contínua. Adicione o seguinte código ao index.js
|
1 |
loja.conectar(); |
O código acima usa o hoodie-store conectar para dizer ao PouchDB para iniciar uma replicação contínua com o banco de dados remoto. Quando recarregarmos nosso banco de dados, os dados que adicionamos na etapa anterior serão automaticamente sincronizados com o servidor. Você pode ver isso usando o URL de administração do Sync Gateway http://localhost:4985/_admin/db/example.
Encerramento
Com tudo o que temos agora, o aplicativo funciona bem com armazenamento de dados off-line e sincronização entre dispositivos em tempo real. Como temos um aplicativo da Web e os usuários provavelmente abririam a página quando estivessem off-line ou em uma conexão instável, podemos fazer com que a página seja carregada durante essas situações e até mesmo carregar rapidamente usando o Service Worker, a API de cache e a API de busca, armazenando em cache o ativo do aplicativo e interceptando a solicitação para eles e retornando as respostas em cache. Isso está além do escopo desta postagem do blog, mas acredito que mostrei como é fácil disponibilizar dados quando estiver off-line e manter todos os clientes de navegador conectados em sincronia, ao mesmo tempo em que o aplicativo carrega os dados rapidamente, e também a mudança de mentalidade do desenvolvimento off-line primeiro.
Abaixo estão GIFs para ver o funcionamento
Você pode obter o código-fonte aqui e dê uma olhada!
Boa noite. Estou migrando do SQLite para o PounchDB, pois acredito que poderei sincronizar dois dispositivos sem a internet, mas utilizando o compartilhamento de rede (HotSpot).
Você acha que esse é um bom caminho a seguir?