Offline First: Your Next Progressive Enhancement Technique?By Craig Buckler
There are three primary reasons your client may demand a native phone app rather than a web app:
- Native apps are faster. This certainly matters if you’re creating the next Angry Birds, but few applications need game-like responsiveness. (That said, with a little care it is possible to create a fast action game using HTML5 technologies. Whether it would work well on a range of devices is another matter).
- The client doesn’t know any better: “Apps are cool! All our competitors have apps — we need one.” A little education solves that issue.
- Mobile apps work offline. But so can web apps — it’s just that the technologies are relatively new and few of us bother. Yet.
Adopting the AppCache to make a web application work offline has been possible for several years. The process defines which files should be cached so the browser can execute the application when Internet connectivity drops. It’s reasonably straight-forward, but:
- Web developers shudder at the thought of connection failure. I’m writing this article on the train and it feels like I’ve lost several major organs. While connectivity is improving, it’s still an issue for commuters and many millions of people who live in remote locations and developing countries.
- Adding offline capabilities to an existing app is difficult. You need to rework Ajax calls and network requests then consider connectivity status changes. But what if we considered it at the start?
Mobile-first is recognized as a good-practice technique. You start with a simple — perhaps linear — view of your site which works on all browsers regardless of age or device. More modern browsers then use media queries to apply styling enhancements and present a more typical desktop view on larger screens. In other words, the layout is progressively enhanced for better browsers using bigger displays.
Can a similar methodology be used for offline applications? The app would presume it was in offline mode and act accordingly. When connectivity resumed, the app would be progressively enhanced to retrieve additional data or save to the cloud.
1. Remove Server Reliance
The majority of application logic must be moved from the server to the client. The server would, in essence, become a lightweight data storage repository but — importantly — the client application should work regardless of the connection status.
2. Create a Client-Side Data Proxy
You cannot depend on Ajax calls. A data proxy would manage all routing, e.g.
- If a connection is available, an Ajax call to the live server can be made (assuming it’s necessary).
- If a connection is not available — or fails during an Ajax call — localStorage, IndexDB or another appropriate client-side storage mechanism is used.
3. Synchronize When Possible
You will require a process to handle synchronization between the client and server when connectivity returns. This could be made efficient using Web Worker background processes and batch uploading/downloading during idle periods.
4. Consider Device Usage Factors
Mobile devices have further complications. For example:
- The act of switching to another app could close the browser. Ideally, your web app should always save application state so the user can return to the place they left.
- The Page Visibility API could be used reduce processing and bandwidth requirements when your app is not running within the opened browser tab.
- Ideally, your app should use the Battery Status API to behave nicely. For example, it could revert to localStorage when battery levels drop below critical levels — even if a connection is available.
5. Test. Then Test Again.
Testing is difficult since your app needs to remain operable regardless of connectivity, e.g.
- The app is installed on a device which doesn’t support localStorage or another essential technology.
- Connectivity drops and restarts at random intervals.
- The app is cached but connectivity drops before the first server communication can be made.
- The app is run on two or more devices at the same time.
Rigorous testing on a range of devices appears to be the only option.
Not every application can take the offline-first plunge; a multi-player action game would be fairly pointless. However, the technique could be used by many web applications assuming it’s considered at the start. I like it, but I suspect the overheads of implementation in existing systems could make separate mobile apps look more cost-effective!
Have you considered offline-first? Are you doing it already? Were there any other complications? Or is it too much effort for too little benefit?