77
Offline strategies for HTML5 web applications Stephan Hochdörfer, bitExpert AG

Offline strategies for HTML5 web applications - pfCongres2012

Embed Size (px)

Citation preview

Page 1: Offline strategies for HTML5 web applications - pfCongres2012

Offline strategies for HTML5 web applicationsStephan Hochdörfer, bitExpert AG

Page 2: Offline strategies for HTML5 web applications - pfCongres2012

Offline strategies for HTML5 web applications

About me

Stephan Hochdörfer, bitExpert AG

Department Manager Research Labs

enjoying PHP since 1999

[email protected]

@shochdoerfer

Page 3: Offline strategies for HTML5 web applications - pfCongres2012
Page 4: Offline strategies for HTML5 web applications - pfCongres2012
Page 5: Offline strategies for HTML5 web applications - pfCongres2012
Page 6: Offline strategies for HTML5 web applications - pfCongres2012
Page 7: Offline strategies for HTML5 web applications - pfCongres2012
Page 8: Offline strategies for HTML5 web applications - pfCongres2012
Page 9: Offline strategies for HTML5 web applications - pfCongres2012
Page 10: Offline strategies for HTML5 web applications - pfCongres2012
Page 11: Offline strategies for HTML5 web applications - pfCongres2012
Page 12: Offline strategies for HTML5 web applications - pfCongres2012
Page 13: Offline strategies for HTML5 web applications - pfCongres2012

Offline strategies for HTML5 web applications

[...] we take the next step, announcing 2014 as the target for

Recommendation.Jeff Jaffe, Chief Executive Officer, World Wide Web Consortium

Page 14: Offline strategies for HTML5 web applications - pfCongres2012

What does „offline“ mean?

Offline strategies for HTML5 web applications

Page 15: Offline strategies for HTML5 web applications - pfCongres2012

What does „offline“ mean?

Offline strategies for HTML5 web applications

Application Cache vs. Offline Storage

Page 16: Offline strategies for HTML5 web applications - pfCongres2012

<!­­ clock.html ­­><!DOCTYPE HTML><html> <head>  <title>Clock</title>  <script src="clock.js"></script>  <link rel="stylesheet" href="clock.css"> </head> <body>  <p>The time is: <output id="clock"></output></p> </body></html>

/* clock.css */output { font: 2em sans­serif; }

/* clock.js */setTimeout(function () {    document.getElementById('clock').value = new Date();}, 1000);

Application Cache for static resources

Offline strategies for HTML5 web applications

Page 17: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache for static resources

Offline strategies for HTML5 web applications

CACHE MANIFEST# 2012­09­16clock.htmlclock.cssclock.js

cache.manifest - must be served using the text/cache-manifest MIME type.

Page 18: Offline strategies for HTML5 web applications - pfCongres2012

<!­­ clock.html ­­><!DOCTYPE HTML><html manifest="cache.manifest"> <head>  <title>Clock</title>  <script src="clock.js"></script>  <link rel="stylesheet" href="clock.css"> </head> <body>  <p>The time is: <output id="clock"></output></p> </body></html>

Application Cache for static resources

Offline strategies for HTML5 web applications

Page 19: Offline strategies for HTML5 web applications - pfCongres2012

CACHE MANIFEST# 2012­09­16

NETWORK:data.php

CACHE:/main/home/main/app.js/settings/home/settings/app.jshttp://myhost/logo.pnghttp://myhost/check.pnghttp://myhost/cross.png

Application Cache for static resources

Offline strategies for HTML5 web applications

Page 20: Offline strategies for HTML5 web applications - pfCongres2012

CACHE MANIFEST# 2012­09­16

FALLBACK:/ /offline.html

NETWORK:*

Application Cache for static resources

Offline strategies for HTML5 web applications

Page 21: Offline strategies for HTML5 web applications - pfCongres2012

Scripting the Application Cache

Offline strategies for HTML5 web applications

// events fired by window.applicationCachewindow.applicationCache.onchecking = function(e) {log("Checking for updates");}window.applicationCache.onnoupdate = function(e) {log("No updates");}window.applicationCache.onupdateready = function(e) {log("Update ready");}window.applicationCache.onobsolete = function(e) {log("Obsolete");}window.applicationCache.ondownloading = function(e) {log("Downloading");}window.applicationCache.oncached = function(e) {log("Cached");}window.applicationCache.onerror = function(e) {log("Error");}

// Log each filewindow.applicationCache.onprogress = function(e) {  log("Progress: downloaded file " + counter);  counter++;};

Page 22: Offline strategies for HTML5 web applications - pfCongres2012

Scripting the Application Cache

Offline strategies for HTML5 web applications

// Check if a new cache is available on page load.window.addEventListener('load', function(e) {  window.applicationCache.addEventListener('updateready',  function(e) {

    if(window.applicationCache.status ==         window.applicationCache.UPDATEREADY) {      // Browser downloaded a new app cache.      // Swap it in and reload the page      window.applicationCache.swapCache();      if (confirm('New version is available. Load it?)) {        window.location.reload();      }    } else {      // Manifest didn't changed.    }  }, false);

}, false);

Page 23: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache – Some gotchas!

Offline strategies for HTML5 web applications

Page 24: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache – Some gotchas!

Offline strategies for HTML5 web applications

1. Files are always(!) served from the application cache.

Page 25: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache – Some gotchas!

Offline strategies for HTML5 web applications

2. The application cache only updates if the content of the manifest itself

has changed!

Page 26: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache – Some gotchas!

Offline strategies for HTML5 web applications

3. If any of the files listed in the CACHE section can't be retrieved, the

entire cache will be disregarded.

Page 27: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache – Some gotchas!

Offline strategies for HTML5 web applications

4. If the manifest file itself can't be retrieved, the cache will ignored!

Page 28: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache – Some gotchas!

Offline strategies for HTML5 web applications

5. Non-cached resources will not load on a cached page!

Page 29: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache – Some gotchas!

Offline strategies for HTML5 web applications

6. The page needs to be reloaded, otherwise the new resources do not

show up!

Page 30: Offline strategies for HTML5 web applications - pfCongres2012

Application Cache – Some gotchas!

Offline strategies for HTML5 web applications

7. To avoid the risk of caching manifest files set expires headers!

Page 31: Offline strategies for HTML5 web applications - pfCongres2012

The Data URI scheme

Offline strategies for HTML5 web applications

Page 32: Offline strategies for HTML5 web applications - pfCongres2012

<!DOCTYPE HTML><html> <head>  <title>The Data URI scheme</title>  <style type="text/css">  ul.checklist li {    margin­left: 20px;    background: white url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==') no­repeat scroll left top;}  </style> </head> <body>  <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot"> </body></html>

The Data URI scheme

Offline strategies for HTML5 web applications

Page 33: Offline strategies for HTML5 web applications - pfCongres2012

Storing dynamic data locally (in HTML5)

Offline strategies for HTML5 web applications

Page 34: Offline strategies for HTML5 web applications - pfCongres2012

Storing dynamic data locally (in HTML5)

Offline strategies for HTML5 web applications

Web Storage, Web SQL Database, IndexedDB, File API

Page 35: Offline strategies for HTML5 web applications - pfCongres2012

Web Storage

Offline strategies for HTML5 web applications

Page 36: Offline strategies for HTML5 web applications - pfCongres2012

Web Storage

Offline strategies for HTML5 web applications

Very convenient form of offline storage: simple key-value store

Page 37: Offline strategies for HTML5 web applications - pfCongres2012

Web Storage: 2 different types

Offline strategies for HTML5 web applications

localStorage vs. sessionStorage

Page 38: Offline strategies for HTML5 web applications - pfCongres2012

var myVar = 123;var myObj = {name: "Stephan"};

// write scalar value to localStoragelocalStorage['myVar'] = myVar;

// read scalar value from localStoragemyVar = localStorage['myVar'];

// write object to localStoragelocalStorage['myObj'] = JSON.stringify(myObj);

// read object from localStoragemyObj = JSON.parse(localStorage['myObj']);

Web Storage: localStorage example

Offline strategies for HTML5 web applications

Page 39: Offline strategies for HTML5 web applications - pfCongres2012

var myVar = 123;var myObj = {name: "Stephan"};

// write scalar value to sessionStoragesessionStorage['myVar'] = myVar;

// read scalar value from sessionStoragemyVar = sessionStorage['myVar'];

// write object to sessionStoragesessionStorage['myObj'] = JSON.stringify(myObj);

// read object from sessionStoragemyObj = JSON.parse(sessionStorage['myObj']);

Web Storage: sessionStorage example

Offline strategies for HTML5 web applications

Page 40: Offline strategies for HTML5 web applications - pfCongres2012

function supports_local_storage() {  try {    return 'localStorage' in window &&               window['localStorage'] !== null;  } catch(e){    return false;  }}

Web Storage: Does my browser support it?

Offline strategies for HTML5 web applications

Page 41: Offline strategies for HTML5 web applications - pfCongres2012

Web Storage: Pro

Offline strategies for HTML5 web applications

Most compatible format up to now.

Page 42: Offline strategies for HTML5 web applications - pfCongres2012

Web Storage: Con

Offline strategies for HTML5 web applications

The data is not structured.

Page 43: Offline strategies for HTML5 web applications - pfCongres2012

Web Storage: Con

Offline strategies for HTML5 web applications

No transaction support!

Page 44: Offline strategies for HTML5 web applications - pfCongres2012

Web SQL Database

Offline strategies for HTML5 web applications

Page 45: Offline strategies for HTML5 web applications - pfCongres2012

Web SQL Database

Offline strategies for HTML5 web applications

An offline SQL database based on SQLite, an general-purpose SQL engine.

Page 46: Offline strategies for HTML5 web applications - pfCongres2012

Web SQL Database

Offline strategies for HTML5 web applications

function prepareDatabase(ready, error) {  return openDatabase('documents', '1.0',     'Offline document storage', 5*1024*1024, function (db) {    db.changeVersion('', '1.0', function (t) {      t.executeSql('CREATE TABLE docids (id, name)');    }, error);  });}

function showDocCount(db, span) {  db.readTransaction(function (t) {    t.executeSql('SELECT COUNT(*) AS c FROM docids', [],       function (t, r) {         span.textContent = r.rows[0].c;      }, function (t, e) {         // couldn't read database         span.textContent = '(unknown: ' + e.message + ')';    });  });}

Page 47: Offline strategies for HTML5 web applications - pfCongres2012

Web SQL Database: Pro

Offline strategies for HTML5 web applications

It`s a SQL database within the browser!

Page 48: Offline strategies for HTML5 web applications - pfCongres2012

Web SQL Database: Con

Offline strategies for HTML5 web applications

It`s a SQL database within the browser!

Page 49: Offline strategies for HTML5 web applications - pfCongres2012

Web SQL Database: Con

Offline strategies for HTML5 web applications

SQLite is slooooow!

Page 50: Offline strategies for HTML5 web applications - pfCongres2012

Web SQL Database: Con

Offline strategies for HTML5 web applications

The specification is no longer part of HTML5!

Page 51: Offline strategies for HTML5 web applications - pfCongres2012

IndexedDB

Offline strategies for HTML5 web applications

Page 52: Offline strategies for HTML5 web applications - pfCongres2012

IndexedDB

Offline strategies for HTML5 web applications

A nice compromise between Web Storage and Web SQL Database giving

you the best of both worlds.

Page 53: Offline strategies for HTML5 web applications - pfCongres2012

Web SQL Database vs. IndexedDB

Offline strategies for HTML5 web applications

Category Web SQL IndexedDB

Location Tables contain columns and rows

objectStore contains Javascript objects and keys

Query Mechanism

SQL Cursor APIs, Key Range APIs, and Application Code

Transaction Lock can happen on databases, tables, or rows on READ_WRITE transactions

Lock can happen on database VERSION_CHANGE transaction, on an objectStore READ_ONLY and READ_WRITE transactions.

Transaction Commits

Transaction creation is explicit. Default is to rollback unless we call commit.

Transaction creation is explicit. Default is to commit unless we call abort or there is an error that is not caught.

Page 54: Offline strategies for HTML5 web applications - pfCongres2012

indexedDB.open = function() {  var request = indexedDB.open("todos");  request.onsuccess = function(e) {    var v = "2.0 beta";    todoDB.indexedDB.db = e.target.result;    var db = todoDB.indexedDB.db;    if (v!= db.version) {      var setVrequest = db.setVersion(v);      setVrequest.onfailure = todoDB.indexedDB.onerror;      setVrequest.onsuccess = function(e) {        if (db.objectStoreNames.contains("todo")) {          db.deleteObjectStore("todo");        }        var store = db.createObjectStore("todo", {keyPath: "timeStamp"});        todoDB.indexedDB.getAllTodoItems();      };    } else {      todoDB.indexedDB.getAllTodoItems();    }  };  request.onfailure = todoDB.indexedDB.onerror;};

IndexedDB – Creating an ObjectStore

Offline strategies for HTML5 web applications

Page 55: Offline strategies for HTML5 web applications - pfCongres2012

IndexedDB – Adding data to ObjectStore

Offline strategies for HTML5 web applications

indexedDB.addTodo = function() {  var db = todoDB.indexedDB.db;  var trans = db.transaction(['todo'], IDBTransaction.READ_WRITE);  var store = trans.objectStore('todo');

  var data = {    "text": todoText,    "timeStamp": new Date().getTime()  };

  var request = store.put(data);  request.onsuccess = function(e) {    todoDB.indexedDB.getAllTodoItems();  };  request.onerror = function(e) {    console.log("Failed adding items due to: ", e);  };};

Page 56: Offline strategies for HTML5 web applications - pfCongres2012

IndexedDB – Retrieving data

Offline strategies for HTML5 web applications

function show() {  var request = window.indexedDB.open("todos");  request.onsuccess = function(event) {    var db = todoDB.indexedDB.db;    var trans = db.transaction(["todo"], IDBTransaction.READ_ONLY);    var request = trans.objectStore("todo").openCursor();    var ul = document.createElement("ul");

    request.onsuccess = function(event) {      var cursor = request.result || event.result;      // If cursor is null, enumeration completed      if(!cursor) {        document.getElementById("todos").appendChild(ul);        return;      }

      var li = document.createElement("li");      li.textContent = cursor.value.text;      ul.appendChild(li);      cursor.continue();    }  }}

Page 57: Offline strategies for HTML5 web applications - pfCongres2012

indexedDB.deleteTodo = function(id, text) {  var db = todoDB.indexedDB.db;  var trans = db.transaction(["todo"], IDBTransaction.READ_WRITE);  var store = trans.objectStore("todo");

  var request = store.delete(id);  request.onsuccess = function(e) {    todoDB.indexedDB.getAllTodoItems();  };  request.onerror = function(e) {    console.log("Error Adding: ", e);  };};

IndexedDB – Deleting data

Offline strategies for HTML5 web applications

Page 58: Offline strategies for HTML5 web applications - pfCongres2012

File API

Offline strategies for HTML5 web applications

Page 59: Offline strategies for HTML5 web applications - pfCongres2012

File API

Offline strategies for HTML5 web applications

FileReader API and FileWriter API

Page 60: Offline strategies for HTML5 web applications - pfCongres2012

function onInitFs(fs) {  console.log('Opened file system: ' + fs.name);}

function errorHandler(e) {  console.log('Error: ' + e.code);}

window.requestFileSystem(window.TEMPORARY, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);

File API – Requesting access

Offline strategies for HTML5 web applications

Page 61: Offline strategies for HTML5 web applications - pfCongres2012

window.webkitStorageInfo.requestQuota(    PERSISTENT,     5*1024*1024 /*5MB*/,     function(grantedBytes) {      window.requestFileSystem(PERSISTENT, grantedBytes,          onInitFs, errorHandler);    },     function(e) {      console.log('Error', e);});

File API – Requesting quota

Offline strategies for HTML5 web applications

Page 62: Offline strategies for HTML5 web applications - pfCongres2012

Offline strategies for HTML5 web applications

Page 63: Offline strategies for HTML5 web applications - pfCongres2012

function onInitFs(fs) {  fs.root.getFile('log.txt',   {create: true, exclusive: true},   function(fileEntry) {    // fileEntry.name == 'log.txt'    // fileEntry.fullPath == '/log.txt'  }, errorHandler);}

window.requestFileSystem(window.TEMPORARY, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);

File API – Creating a file

Offline strategies for HTML5 web applications

Page 64: Offline strategies for HTML5 web applications - pfCongres2012

function onInitFs(fs) {  fs.root.getFile('log.txt', {},   function(fileEntry) {    fileEntry.file(function(file) {       var reader = new FileReader();

       reader.onloadend = function(e) {         var txtArea   =               document.createElement('textarea');         txtArea.value = this.result;         document.body.appendChild(txtArea);       };       reader.readAsText(file);    }, errorHandler);  }, errorHandler);}

window.requestFileSystem(window.TEMPORARY, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);

File API – Reading a file

Offline strategies for HTML5 web applications

Page 65: Offline strategies for HTML5 web applications - pfCongres2012

function onInitFs(fs) {  fs.root.getFile('log.txt', {create: true},   function(fileEntry) {    fileEntry.createWriter(function(fileWriter) {

      fileWriter.onwriteend = function(e) {        console.log('Write completed.');      };      fileWriter.onerror = function(e) {        console.log('Write failed: ' + e.toString());      };

      var bb = new BlobBuilder();      bb.append('Lorem Ipsum');      fileWriter.write(bb.getBlob('text/plain'));    }, errorHandler);  }, errorHandler);}

window.requestFileSystem(window.TEMPORARY, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);

File API – Writing to a file

Offline strategies for HTML5 web applications

Page 66: Offline strategies for HTML5 web applications - pfCongres2012

function onInitFs(fs) {  fs.root.getFile('log.txt', {create: false},   function(fileEntry) {    fileEntry.createWriter(function(fileWriter) {

      fileWriter.seek(fileWriter.length);

      var bb = new BlobBuilder();      bb.append('Hello World');      fileWriter.write(bb.getBlob('text/plain'));    }, errorHandler);  }, errorHandler);}

window.requestFileSystem(window.TEMPORARY, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);

File API – Appending data to a file

Offline strategies for HTML5 web applications

Page 67: Offline strategies for HTML5 web applications - pfCongres2012

function onInitFs(fs) {  fs.root.getFile('log.txt', {create: false},   function(fileEntry) {    fileEntry.remove(function() {      console.log('File removed.');    }, errorHandler);   }, errorHandler);}

window.requestFileSystem(window.TEMPORARY, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);

File API – Deleting a file

Offline strategies for HTML5 web applications

Page 68: Offline strategies for HTML5 web applications - pfCongres2012

File API – Creating directories

Offline strategies for HTML5 web applications

function onInitFs(fs) {   fs.root.getDirectory('MyFolder', {create: true},    function(dirEntry) {    // do stuff...    }, errorHandler);}

window.requestFileSystem(window.TEMPORARY, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);

Page 69: Offline strategies for HTML5 web applications - pfCongres2012
Page 70: Offline strategies for HTML5 web applications - pfCongres2012

File API – Browser support?

Offline strategies for HTML5 web applications

Up to now: Chrome only

Page 71: Offline strategies for HTML5 web applications - pfCongres2012

File API – Browser support?

Offline strategies for HTML5 web applications

But: idb.filesystem.js

Page 72: Offline strategies for HTML5 web applications - pfCongres2012

Am I online?

Offline strategies for HTML5 web applications

Page 73: Offline strategies for HTML5 web applications - pfCongres2012

document.body.addEventListener("online", function () {  // browser is online!}

document.body.addEventListener("offline", function () {  // browser is not online!}

Am I online?

Offline strategies for HTML5 web applications

Page 74: Offline strategies for HTML5 web applications - pfCongres2012

$.ajax({  dataType: 'json',  url: 'http://myappurl.com/ping',  success: function(data){    // ping worked  },  error: function() {    // ping failed ­> Server not reachable  }});

Am I online? Another approach...

Offline strategies for HTML5 web applications

Page 75: Offline strategies for HTML5 web applications - pfCongres2012
Page 76: Offline strategies for HTML5 web applications - pfCongres2012

Thank you!

Page 77: Offline strategies for HTML5 web applications - pfCongres2012

http://joind.in/7073