There’s an old expression, that there are only 2 hard problems in computing: naming, cache invalidation and off-by-one errors. Building offline web apps is all about those hard problems. There are some different ways of storing stuff — such as html5 caching, html5 storage, sqllite, and even native stores such as contacts and calendars — and we’ll sing their praises. But the really hard problems are knowing what to store, whether the stuff is still good or needs refreshing, how much to store, how to resolve conflicts between the client and server, how to integrate with data-specific stores, all in a bewildering cacophony of network and storage limited devices. We’ll spend the bulk of our time on these hard problems, which is probably more useful than api description and sample code.
Dave Orchard is Mobile Architect at Salesforce.com and located in Vancouver, Canada. This means being involved in many mobile platforms, architectures, tools, technologies and APIs. Prior to that, he was a co-founder of Ayogo Games and focused on iPhone and ruby/merb/mysql based casual social games. Back further in the mists of time, he was the Web standards lead for BEA Systems for 7 years, including being elected three times to 2 year terms on the W3C Technical Architecture Group chaired by Sir Tim Berners-Lee.
Follow Dave on Twitter: @DaveO
4. Web Storage Aka HTML5 Storage SessionStorage Scoped to session No sharing across windows LocalStorage Persistent Shared across windows Size: 5M, 10M, expandable
5. Web storage API setItem(key, value) sessionStorage.setItem(key, value) sessionStorage.key=value sessionStorage[‘key’]=value getItem(key) removeItem(key) length key(index) clear
6. WebStorage data types String That’s it. Use JSON to serialize/deserialize structures Json.org/json2.js Careful of serializing too much
8. HTML5 Cache Manifest Central resource for html5 caching <!DOCTYPE HTML> <html manifest=“/appcache.manifest”> <body> </body> </html> Every page in your app must refer to the manifest
9. Serving Cache Manifest Must be content-type text/cache-manifest Document name must end in .manifest Watch out for HTTP caching the manifest Make sure cache file gets refreshed when you refresh Can tell if clearing the cache works Or just the checking event fired (events coming up) Configure server to tell browser to not cache manifest
12. Cache Manifest loading process HTTP load .manifest file Previously mentioned HTTP Caching issue Determine if new version of cache manifest Uses HTTP last-modified Change manifest file every time file changes Automate! Download
13. Cache events checking downloading progress with how many files downloaded, to go noupdate updateready then do window.applicationCache.swapCache()
14. Tips/Reference Modernizr.applicationcache Charles Proxy http://jonathanstark.com/blog/2009/09/27/debugging-html-5-offline-application-cache/ Oh, not in iOS for webkit http://stackoverflow.com/questions/4361948/offline-ios-web-app-loads-my-manifest-but-doesnt-work-offline Well, maybe from 4.3.2 http://diveintohtml5.org/offline.html
15. Web SQL OpenDatabase(name, version, descr, size) var db = openDatabase(‘mdb’,’1.0’,’hello world db’, 1*1024*1024) Version # is magic db.transaction(function(tx){ tx.executeSQL(‘CREATE TABLE test(id,text)’); tx.executeSQL(‘INSERT INTO test VALUES(1,”hello”)’); tx.executeSQL(‘SELECT * FROM foo’, [], callback); }); function(tx, results){// results.rows.items(i).text}
20. Naming Web arch anyone? http://www.w3.org/TR/webarch/ Also Roy’s thesis
21.
22. Representations http://lists.w3.org/Archives/Public/www-tag/2002Oct/0079.html So, then, how do you bend a spoon? Simple. Drop a graphics processor onto the interface such that the representations are morphed. The spoon appears to bend because you have no way of distinguishing one implementation from another, unless you happen to be the One in control of the implementation. And, because of that, bending the representations is sufficient for other observers to think that you have actually bended the spoon.
23. Cache Invalidation aka bending the spoon How about client-side write? Phases 0. No client side write 1. Write to server, refresh cache 2. Write to cache, then server Sync everything Deltas Choices depend upon latency What if network breaks or device shuts off partway? When to update UI?
24. Deltas Client actions stored as deltas in command queue Server responds with absolute or delta? Combine with Server updates If server responds with invalid state or denies command have to drain the queue and stop Hold off on UI updates if many pending requests http://googlecode.blogspot.com/2009/06/gmail-for-mobile-html5-series-cache.html
25. Offline detection navigator.onLine is usually just wrong Maybe message fails Or even worse, slow connection with partial message Need a ping service Tip: provide a config that you can turn on/off during app
26. The joy that is reliable messaging Asynchronous messaging Never do synchronous for writes No response could mean: Outbound message lost Failure on server Where on server processing? Inbound message lost Retry synchronous could mean dup messages Duplicate detection Try for idempotency
27. But wait, there’s more: multi-party rm scenario User buys in-app purchase Apple send back confirmation with receipt Verify receipt with your server Server talks to apple Respond to device
28. Security none Good luck doing crypto in js Oh, right, export laws. That’s why apple asks you every time PIN/Password to access crypto item. Where to store the key? Need native store for security Even better, use native code for crypto
29. Outline Easy stuff Web Storage App Cache Web SQL Hard stuff Naming Cache invalidation Writing Oh, and security