OnConnectionLost: The life of an offline web application - JSUnconf 2015
-
Upload
johannes-thoenes -
Category
Technology
-
view
240 -
download
2
Transcript of OnConnectionLost: The life of an offline web application - JSUnconf 2015
J S U n c o n f 2 0 1 5
ON CONNECTION LOSTThe life of an offline web application &
war stories about generating PDFs in the browser
#jsunconf #offlinefirst @thoughtworks
@sgrewenig @jthoenes
OFFLINE ??!
WHAT ISOFFLINE ?
STUPIDCLIENT
MORE LOGICCLIENT-SIDE
“INDEPENDENT”CLIENT
WHY ?
HOW ?
CLIENT AVAILABLE OFFLINE
2 DATA AVAILABLE OFFLINE
3 DATA CHANGES OFFLINE
1
CLIENT AVAILABLE OFFLINE1
YOU LEARNED ABOUT APPLICATION CACHE ALREADY, RIGHT?
14
APP CACHE
APP CACHE
APP CACHE
INDEX.HTML
1 <!doctype html> 2 <html ... manifest="appcache.manifest"> . <!-- (...) --> 54 </html>
APPCACHE.MANIFEST 1 CACHE MANIFEST 2 # rev 1 - 2014-10-03T13:50:18.799Z 3 4 CACHE: 5 404.html 6 favicon.ico 7 scripts/scripts.js # (...) 111 112 NETWORK: 113 * 114 115 FALLBACK: 116 / /offline.html
APPCACHE.MANIFEST 1 CACHE MANIFEST 2 # rev 1 - 2014-10-03T13:50:18.799Z 3 4 CACHE: 5 404.html 6 favicon.ico 7 scripts/scripts.js # (...) 111 112 NETWORK: 113 * 114 115 FALLBACK: 116 / /offline.html
APPCACHE.MANIFEST 1 CACHE MANIFEST 2 # rev 1 - 2014-10-03T13:50:18.799Z 3 4 CACHE: 5 404.html 6 favicon.ico 7 scripts/scripts.js # (...) 111 112 NETWORK: 113 * 114 115 FALLBACK: 116 / /offline.html
APPCACHE.MANIFEST 1 CACHE MANIFEST 2 # rev 1 - 2014-10-03T13:50:18.799Z 3 4 CACHE: 5 404.html 6 favicon.ico 7 scripts/scripts.js # (...) 111 112 NETWORK: 113 * 114 115 FALLBACK: 116 / /offline.html
APPCACHE.MANIFEST 1 CACHE MANIFEST 2 # rev 1 - 2014-10-03T13:50:18.799Z 3 4 CACHE: 5 404.html 6 favicon.ico 7 scripts/scripts.js # (...) 111 112 NETWORK: 113 * 114 115 FALLBACK: 116 / /offline.html
EVENTS
CHECKING DOWNLOADING PROGRESS UPDATE READY
ADDITIONAL CACHE
CLIENT AVAILABLE OFFLINE
2 DATA AVAILABLE OFFLINE
1
31
//Store localStorage.town = “Antwerpen”
//Retrieve alert(localStorage.town)
WEBSTORAGEEasy to use key/value store Synchronous API
INDEXED DB
33
10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly'); 32 var store = trans.objectStore('name'); 33 var getRequest = store.get('4'); 34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount'); 43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15)); 44 cursorRequest.onsuccess = // ...
THE API
10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly'); 32 var store = trans.objectStore('name'); 33 var getRequest = store.get('4'); 34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount'); 43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15)); 44 cursorRequest.onsuccess = // ...
THE API
10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly'); 32 var store = trans.objectStore('name'); 33 var getRequest = store.get('4'); 34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount'); 43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15)); 44 cursorRequest.onsuccess = // ...
THE API
10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly'); 32 var store = trans.objectStore('name'); 33 var getRequest = store.get('4'); 34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount'); 43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15)); 44 cursorRequest.onsuccess = // ...
THE API
10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly'); 32 var store = trans.objectStore('name'); 33 var getRequest = store.get('4'); 34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount'); 43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15)); 44 cursorRequest.onsuccess = // ...
THE API
10 var dbRequest = indexedDB.open('db_name', ‘1’);
31 var trans = database.transaction(['name'], ‘readonly'); 32 var store = trans.objectStore('name'); 33 var getRequest = store.get('4'); 34 getRequest.onsuccess = // …
42 var index = store.index('stockAmount'); 43 var cursorRequest = index.openCursor(IDBKeyRange.lower(15)); 44 cursorRequest.onsuccess = // ...
THE API
MIGRATIONS
ONUPGRADE
NEEDED
FILESYSTEM APIFILE API
44
ADD IMAGE
filesystem:http://thedomain/persistent/xyz.jpg
45
GET IMAGE
IE 106.1YES YEShttp://caniuse.com/#search=fileapi
YES NONONOhttp://caniuse.com/#search=filesystem
CLIENT AVAILABLE OFFLINE
2 DATA AVAILABLE OFFLINE
3 DATA CHANGES OFFLINE
1
DATA SYNCHRONISATION
CAPTURING1 CHANGES
QUEUE2
PROCESSING3
<<<<<<< HEAD
Hamburger is better than Berliner.=======
Berlin is better than Hamburger.>>>>>>> d237ef28dc3fab5dcccc63f580bfa7780f
OR
SIZE OF DATA ?
STRUCTURE OF DATA ?
SENSITIVE DATA ?
POTENTIAL FOR DATA CONFLICTS ?
BROWSER SUPPORT ?
AMOUNT OF FUNCTIONALITY TO WORK OFFLINE ?
61
CHALLENGE REQUIREMENTS
OFFLINE FIRST & EARLY
63
EXPLORE THE POSSIBILITIES
PDF IN THE BROWSER
"sections": [{ "blocks": [{ "contentItems": [ { "uid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "wysiwyg": "<p>Decorative <i>deer</i> figures in a set of 2<\/p><img our-src=“aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee.png”>” }, { "libraryItemUid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "uid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "wysiwyg": "<p>There may be <strong>no sign</strong> of a seam in the material. [FT-PLACEHOLDER]<\/p>" }, { "libraryItemUid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "uid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "wysiwyg": "<p>Set comprises a large deer and a small deer [FT-PLACEHOLDER]<\/p>" },
HAVE A LOOK !
67
USE THE BROWSER TO PRINT?
68
var doc = new jsPDF();doc.text(20, 20, 'Hello world.');doc.save('Test.pdf');
https://github.com/MrRio/jsPDF
PDFDocument = require 'pdfkit'
doc = new PDFDocumentdoc.pipe fs.createWriteStream('output.pdf')doc.font('fonts/PalatinoBold.ttf') .fontSize(25) .text('Some text with an embedded font!', 100, 100)
doc.addPage() .fontSize(25) .text('Here is some vector graphics...', 100, 100)
doc.end()https://github.com/devongovett/pdfkit
pdfMake.createPdf({ content: [ { text: 'This paragraph will have a bigger font', fontSize: 15 }, { text: [ { text: 'restyle part of it and make it bigger ', fontSize: 15 }, 'than the rest.' ] } ]}).open();
https://github.com/bpampuch/pdfmake
SHORT DEMO?
73
74
HTML -> PDF PARSER
75
PAGE BREAKS
76
LANDSCAPE
77
95 CHARACTERS
78
IMAGE WRAPPING
79
https://github.com/TW-QEN/pdfmake#develop
THANKS@SGREWENIG @JTHOENES@THOUGHTWORKS
IE 10YESYES YEShttp://caniuse.com/#search=appcache
IE 107.1YES YEShttp://caniuse.com/#search=indexeddb
YESYESYES YEShttp://caniuse.com/#search=webstorage