Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Jurassic JavaScriptPark: rodando offline até na...

Jurassic JavaScriptPark: rodando offline até na ilha Nublar!

Poucos se beneficiam das funcionalidades offline nos browsers. Vamos descobrir como o uso de localStorage, WebSQL, AppCache e ServiceWorkers, numa arquitetura de sincronização offline e segura, pode ser valioso! Vamos deixar sua aplicação ativa até na ilha Nublar!

Eduardo Matos

December 19, 2015
Tweet

More Decks by Eduardo Matos

Other Decks in Programming

Transcript

  1. UX Sensação de rapidez Não deve ser frustrante Deve ser

    honesta sobre conectividade Não deve perder informações
  2. PROBLEMAS O AppCache só atualiza o conteúdo do manifesto se

    ele mesmo for atualizado Os arquivos sempre virão do ApplicationCache mesmo se você estiver online … Recomendo fortemente a leitura: http://sergiolopes.org/palestra-appcache-html5-offline/
  3. MAS AINDA NÃO É O IDEAL… O Application Cache é

    ok para cachear assets Mas precisamos de algo mais evoluído para controlar de forma programática, sem modo texto
  4. if ('serviceWorker' in navigator) { navigator.serviceWorker.register( '/js/sw.js',
 { scope: '/'

    }
 ).then(function(reg) { if(reg.installing) { console.log('Service worker installing'); } else if(reg.waiting) { console.log('Service worker installed'); } else if(reg.active) { console.log('Service worker active'); } }).catch(function(error) { // registration failed console.log('Registration failed with ' + error); }); };
  5. // /js/sw.js this.addEventListener('install', function(event) { event.waitUntil( caches.open('v1').then(function(cache) { return cache.addAll([

    '/index.html', '/js/app.js', '/css/styles.css', '/images/gallery/jurassic_park.jpg' ]); }) ); });
  6. this.addEventListener('fetch', function(event) { var response; event.respondWith(caches.match(event.request).catch(function() { return fetch(event.request); }).then(function(r)

    { response = r; caches.open('v1').then(function(cache) { cache.put(event.request, response); }); return response.clone(); }).catch(function() { return caches.match('/images/gallery/jurassic_park.jpg'); })); });
  7. PRÓS CONTRAS Simples de implementar Sem uma biblioteca o controle

    fica complicado Browsers suportam amplamente Problemas de segurança (Cookie stealing e XSS, CSFR, etc.) Ótimo para informações curtas Limite de 4093 bytes
  8. basket.require( { url: "jquery.js" }, { url: "underscore.js" }, {

    url: "backbone.js" } ); var req; var ttl; basket.require({ url: "jquery.min.js", key: "jquery" }); req = basket.get("jquery");
  9. PRÓS CONTRAS Fácil implementação Limite de 5M por domínio Amplo

    suporte É síncrono Melhor segurança Os dados ficam lá eternamente, mesmo não visitando mais o site
  10. // name, version, description, size (bytes) var db = openDatabase("dinos",

    "1", "todo list example db", 2 * 1024 * 1024); // executeSql // (SQL string, arguments, success, error) db.transaction( function (tx) { tx.executeSql( "CREATE TABLE IF NOT EXISTS dinos (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)", [], function (tx, results) { console.log("ok!"); }, function (err) { console.log("error!", err); } ); } );
  11. db.transaction( function (tx) { tx.executeSql( "SELECT * FROM dinos WHERE

    id > ?", ["1"], function (tx, results) { var row = ""; for (var i=0; i<results.rows.length; i++) { console.log("Dino name:", results.rows.item(i).name); } }, function (err) { console.log("query problems...", err); } ); }, function (err) { console.log("transaction problems...", err); } );
  12. db.transaction( function (tx) { tx.executeSql( "INSERT INTO dinos(name) VALUES(?)", ["Megalosaurus"],

    function ( tx, results ) { console.log("ok! inserted!"); }, function (err) { console.log("not inserted :("); } ); }, function (err) { console.log("inserting problems...", err); }, function () { console.log("transaction completed!"); } );
  13. PRÓS CONTRAS Banco de dados no browser Sintaxe SQL pode

    assustar quem não está acostumado Performance razoável Deprecated. Apenas alguns browsers ainda dão suporte. Não é full SQL supported. Crash com muitos dados (10,000 rows já apresenta certa lentidão)
  14. var request = window.indexedDB.open("DinoDatabase", 1); request.onerror = function (event) {

    console.log("Error", event.target.errorCode); }; request.onupgradeneeded = function (event) { db = event.target.result; if ( db.objectStoreNames.contains("dinos") ) { db.deleteObjectStore("dinos"); } var store = db.createObjectStore("dinos", { autoIncrement: true }); };
  15. request.onsuccess = function (event) { db = event.target.result; var trans

    = db.transaction(["dinos"], "readwrite"); var transRequest = trans.objectStore("dinos"); transRequest.onsuccess = function (event) { var result = transRequest.result || event.result; if (!result) return; console.log("dino", result.key, result.value.text); cursor.continue(); } var dinoName = "Velociraptor"; var storeRequest = transRequest.put(dinoName); storeRequest.onsuccess = function (event) { console.log(event.target.result) } storeRequest.onerror = function (event) { console.log(event) } };
  16. PRÓS CONTRAS Mais evoluído que localStorage Suporte em browsers modernos

    Pode trabalhar com uma quantidade maior de dados Se o usuário fechar o browser no meio de uma transaction, o dado se perde Pode trabalhar em Workers Mais complexo que as outras formas de armazenamento Tem índices
  17. // In localStorage, we would do: var obj = {

    value: "Dinofauro" }; localStorage.setItem("dino", JSON.stringify(obj)); console.log(obj.value); // With localForage, we use callbacks: localforage.setItem("dino", obj, function (err, result) { console.log(result.value); });
  18. var db = new PouchDB("dinoDB"); db.put({ _id: 1, name: "Dinofauro

    Fefiz" }); db.changes().on("change", function () { console.log("Alterou alfuma foisa"); }); db.replicate.to("http://dinofauro.com/dinoDB");
  19. SEJA SENSATO! Em alguns casos o cenário offline nem pode

    existir, como em serviços de chat, transmissão de áudio e vídeo, e etc. O esforço vale a pena somente quando o cenário pede esse tipo de arquitetura