Your SlideShare is downloading. ×
0
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Taking Web Apps Offline
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Taking Web Apps Offline

1,400

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,400
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Takingweb appsoffline pedro@morais.it @pedromoraisGDG Portugal DevFest morais on app.net March ’13
  • 2. Offline webapps - why? no network connection required faster startup keep data local
  • 3. The Road to Offline user data assets
  • 4. 1. user data
  • 5. localStorage *and sessionStorage
  • 6. localstorage Simple APIwindow.localStorage[‘hello’] = ‘world’;
  • 7. localStorage Can store a JSON stringwindow.localStorage[‘helloJSON’] = JSON.stringify({‘key1’: ‘world’, ‘key2’: ‘Lisbon’});
  • 8. 92.25% http://caniuse.com/indexeddb
  • 9. localStorage limitations Storage Limits Spec - 5 Mb Firefox - can adjusted Chrome - 2600k chars (5 mb in UTF-16) IE - 5000k chars
  • 10. localStorage limitations Sync API window.localStorage[‘sloooow’] = ‘imagine a 1 MB string here’;
  • 11. sql storage
  • 12. sql storage work stopped November ’10 sqlite was used in all implementations (webkit, opera)mozilla & microsoft: “not gonna happen”
  • 13. 48.32% http://caniuse.com/sql-storage
  • 14. sql storagehttp://nparashuram.com/IndexedDBShim/ indexed db polyfill over websql
  • 15. indexed db
  • 16. indexed db Async APIvar request = indexedDB.doStuff();request.onerror = function(event) { ...};request.onsuccess = function(event) { ...};
  • 17. indexed db Opening a databasevar request = indexedDB.open("MyTestDatabase");request.onerror = ...var db;request.onsuccess = function(event) { db = request.result;};
  • 18. creating the schemavar request = indexedDB.open("MyTestDatabase", 5);...request.onupgradeneeded = function(event) { var db = event.target.result; ...};
  • 19. creating the schema# student: cardNumber, name, email, ...request.onupgradeneeded = function(event) { var db = event.target.result; var studentsStore = db.createObjectStore("students", { keyPath: "cardNumber" }); studentsStore.createIndex("nameIndex", "name", { unique: false }); studentsStore.createIndex("emailIndex", "email", { unique: true });};
  • 20. adding datavar transaction = db.transaction(["students"], "readwrite");transaction.oncomplete = function(event) {  alert("All done!");};...// transactions go away when you// return to the event loop// without making a request
  • 21. adding data...var objectStore = transaction.objectStore("customers");aStudent = { ‘studentCard’: ‘44124’, ‘name’: ‘Pedro Morais’, ‘email’: ‘pedro@morais.it}var request = objectStore.add(aStudent);request.onsuccess = function(event) {  // event.target.result == aStuddent.studentCard};
  • 22. updating data...var objectStore = transaction.objectStore("customers");aStudent = { ‘studentCard’: ‘44124’, ‘name’: ‘Pedro Morais with updated name’, ‘email’: ‘pedro@morais.it}var request = objectStore.put(aStudent);request.onsuccess = function(event) {  // event.target.result == aStuddent.studentCard};
  • 23. deleting data...var objectStore = transaction.objectStore("customers");var request = objectStore.delete(‘44124’);request.onsuccess = function(event) { // deleted};
  • 24. getting datavar transaction = db.transaction(["students"]);var objectStore = transaction.objectStore("customers");var request = objectStore.get(‘44124’);request.onsuccess = function(event) { console.log(“Name is “, request.result.name);};
  • 25. using a cursor....var request = objectStore.openCursor();request.onsuccess = function(event) { var c = event.target.result;  if (c) {    console.log ("Student " + c + " is named " + c.value.name);    cursor.continue();  } else {    console.log("Done!");  }};
  • 26. using an index...var index = objectStore.index("name");index.get("Pedro Morais").onsuccess = function(event) {  console.log("Email=" + event.target.result.email);};// if name is not unique// you get the first entry that matches
  • 27. using an index + cursor...var index = objectStore.index("name");var request = index.openCursor(IDBKeyRange.only("Pedro Morais"));request.onsuccess = function(event) {  var c = event.target.result;  if (c) {    // c.key is a name, like "Pedro Morais", // c.value is the whole object.    console.log("Name: " + cursor.key + “Email: " + cursor.value.email);    cursor.continue();  }};
  • 28. cursor key rangesIDBKeyRange.only("Pedro Morais")IDBKeyRange.lowerBound("Pedro")IDBKeyRange.lowerBound("Pedro", true) // don’t inc PedroIDBKeyRange.upperBound("Pedro", true) // don’t inc PedroIDBKeyRange.bound("Pedro", "Vanda", false, true);// include Pedro, don’t include Vanda
  • 29. 46.93% http://caniuse.com/indexeddb
  • 30. 2. assets
  • 31. offline web apps
  • 32. 67.43% http://caniuse.com/offline-apps
  • 33. offline web apps<!DOCTYPE html><html manifest=”cache.appcache”>... cache.appcache must be served as text/cache-manifest
  • 34. cache manifestCACHE MANIFEST# this is a commentcss/styles.cssjs/scripts.jsimages/logo.pngNETWORK:*
  • 35. cache with fallbackCACHE MANIFEST# this is a commentcss/styles.cssjs/scripts.jsimages/logo.pngFALLBACK:/ /offline.htmlNETWORK:*
  • 36. network access not using appcache• user navigates to http://test.com/app.html• browser check if file “app.html” is in cache• browser check if it has not expired• browser checks validity of file using etags (optional)• browser renders the cached or downloaded app.html
  • 37. network access using appcache• user navigates to http://test.com/app.html• browser renders app.html from appcache• in the background: • browser checks if manifest has changed • if it has, browser downloads all files in the manifest (expires, etags still apply) • user only gets new version of app.html the next time!
  • 38. cache manifest versions CACHE MANIFEST # version 50 css/styles.css js/scripts.js images/logo.png NETWORK: *
  • 39. cache manifest versions CACHE MANIFEST css/styles.css?b3c4de js/scripts.js?adf341 images/logo.png?ef3451 NETWORK: * + far future expires
  • 40. cache manifest versions CACHE MANIFEST b3c4de/css/styles.css adf341/js/scripts.js ef3451/images/logo.png NETWORK: * + far future expires
  • 41. conclusion
  • 42. Available today localStorage Indexed DB (+ polyfill) AppCacheTake your web apps offline
  • 43. Thanks! pedro@morais.it @pedromoraisGDG Portugal DevFest morais on app.net March ’13

×