by finne on 02-03-2017

HTML5 offline web apps

march 2017

Offline or local usage of web sites and apps has some nice applications. The most well known is probably a mobile offline web app, that could be almost indistinguishable from a native mobile app.

There are many different technologies and terms you might encounter. Here I will summarise most of these and give some pointers what to use when.

  • Accessing your applications whilst offline.
  • Storing application data offline.
  • Working with the local file system.
  • Data communication between client and server.

If you use all of the above you will be able to create a fully offline web app, that optionally gets new data when online. Each of the technologies described below is known by multiple different names. I have mentioned every name I could find for each tech to prevent some of the confusion I felt myself when diving into this subject.

To find out if a particular technology is supported in a particular browser use caniuse.com.

accessing your app offline

Offline detection

If your app can be both online and offline you will need to find out what state the network is in. The network information API is designed to detect online status, but this is not very reliable yet. There are a number of other offline detection mechanisms, and I recommend using an offline detection library, such as offline.js.

 

Application Cache / AppCache (deprecated)

AppCache is the method of defining web page files to be cached using a cache manifest file, allowing them to work offline on subsequent visits to the page. The manifest file must be served by the HTTP server with the text/cache-manifest Mime type. This can easily be accomplished using an .htaccess directive for Apache webservers:

AddType text/cache-manifest .appcache

This will serve any *.appcache file as manifest. A cache manifest file has 3 sections:

  • CACHE MANIFEST
  • NETWORK
  • FALLBACK

You must be careful with the files you list in the CACHE section because if there is a problem with one of those files, none of those files will work!

The NETWORK section lists areas of your website that you never want to be cached.

The FALLBACK section is a list of redirects to occur in the event of the application going offline.

However, for apps of any significant size and complexity, AppCache is a problematic solution and it is recommended you don't use it. If you really want assets available offline, a better solution may be to grab your assets via XMLHttpRequest and then store them inside an offline datastore. In the near future Service Workers will be ready for use, and present a much better solution to the problem of offline asset storage and use.

Summary:

  • Deprecated.
  • Supported in all major browsers.

 

Service Workers

Service Workers are a method that enables applications to take advantage of persistent background processing, including hooks that enable the bootstrapping of web applications while offline.

Summary:

  • Recommended replacement for AppCache.
  • Supported in FireFox, Chrome.

Storing application data offline

During app usage, you should ensure that its state is saved periodically to the offline data store. Also you might want to save the state locally when user closes the app (though not all technologies allow this).

 

Web Storage / localStorage / Storage API / DOM Storage

Web Storage is a method of storing data locally like cookies, but for larger amounts of data (sessionStorage and localStorage, used to fall under HTML5). Web Storage was designed for smaller amounts of data. It's essentially a strings only key - value storage, with a simplistic synchronous API. Because of this not useful for large data amounts.

The Web Storage API provides mechanisms by which browsers can store key/value pairs, in a much more intuitive fashion than using cookies. The two mechanisms within Web Storage are as follows:

  • sessionStorage maintains a separate storage area for each given origin that's available for the duration of the page session (as long as the browser is open, including page reloads and restores)
  • localStorage does the same thing, but persists even when the browser is closed and reopened.

These mechanisms are available via the Window.sessionStorage and Window.localStorage properties (to be more precise, in supporting browsers the Window object implements the WindowLocalStorage and WindowSessionStorage objects, which the localStorage and sessionStorage properties hang off). Invoking one of these will create an instance of the Storage object, through which data items can be set, retrieved and removed. A different Storage object is used for the sessionStorage and localStorage for each origin. They function and are controlled separately.

Summary:

  • Limit of ~5MB.
  • Access to Web Storage from third-party iFrames is denied if the user has disabled third-party cookies.
  • Since iOS 5.1, Safari Mobile stores localStorage data in the cache folder, which is subject to occasional clean up, at the behest of the OS!
  • Supported in all major browsers.

 

Web SQL (deprecated)

Web SQL is a method of storing data client-side, allows Sqlite database queries for access and manipulation. Web SQL is basically SQLite but embedded in the browser, which would make it accessible to HTML5. However, the Web SQL specification is no longer being maintained and although it is supported on iOS and Android browsers, support may be dropped in the future.

Summary:

  • Deprecated.
  • Supported in Chrome and Safari.

 

IndexedDB

IndexedDB is a method of storing data client-side, allows indexed database queries. Where SQLite provides a typical relational database approach, IndexedDB provides a NoSQL approach. This means that data is stored as objects rather than in tables. NoSQL databases are generally considered to be faster and more scalable than SQL databases, and since there is no pre-defined schema it is really easy to add new data. This is a bit of a double edged sword, this less structured approach isn’t necessarily a good thing in all cases, nor is it a bad thing – it all depends on the circumstance and preference. For easier usage there is dexie.js, a wrapper for IndexedDB that allows fast code development via a nice, simple syntax.

Summary:

  • Supported in all major browsers.

 

localForage

To get up and running quickly with offline data you don't need to choose a specific data storage option: Use localForage instead! This is a handy library that abstracts away the differences in cross browser support for offline data technologies. It provides asynchronous data storage via IndexedDB for browsers that support it; it then falls back to WebSQL for browsers that support that, and localStorage for browsers with even more basic support.

NB: localForage does not work if called from a local file:// uri. You need to serve it using a webserver.

NB: localForage serialises objects, and this does not work for objects with enumerable methods (functions) in them.

Working with the local file system

File / File API

The File API is a method of manipulating file objects in web applications client-side, as well as programmatically selecting them and accessing their data. 

Summary:

  • Supported in all major browsers
  • Access to selected files on the local filesystem.

 

File System API

The File System API is a method of reading and writing files to a sandboxed file system. Only consider using the File System API if you don’t need to support browsers such as Edge, Firefox and Safari.

Summary:

  • Supported by Chrome & Opera
  • Complete access to a sandbox on the local filesystem.

Data communication between client and server

Syncing with server side

Your app should also save its data back to the server periodically. If your app is offline you should consider building a queueing solution that can handle a lack of connectivity, aiming to save the updates once the network is available again. See handy libraries for this such as PouchDB.

All of the technologies below are supported in all major browsers.

 

Polling

To communicate with the server the simplest and wordt solution is Polling. Just fire a request repeatedly from the client to the server to sent or receive data. Very wasteful on resources.

 

Long polling / Hanging GET / COMET

This is a slight variation on polling. In long polling, if the server does not have data available, the server holds the request open until new data is made available. Hence, this technique is often referred to as a "Hanging GET". When information becomes available, the server responds, closes the connection, and the process is repeated. A more advanced version of this technique is COMET.

 

Server-Sent Events / SSE / EventSource

SSE is a method of continuously sending data from a server to the browser, rather than repeatedly requesting it (EventSource interface, used to fall under HTML5). When communicating using SSEs, a server can push data to your app whenever it wants, without the need to make an initial request. In other words, updates can be streamed from server to client as they happen. SSEs open a single unidirectional channel between server and client.

The main difference between Server-Sent Events and long-polling is that SSEs are handled directly by the browser and the user simply has to listen for messages. Why would you choose Server-Sent Events over WebSockets? In some scenarios data doesn't need to be sent from the client. You simply need updates from some server action. A few examples would be friends' status updates, stock tickers, news feeds, or other automated data push mechanisms (e.g. updating a client-side Web SQL Database or IndexedDB object store). If you'll need to send data to a server, XMLHttpRequest is always a friend.

SSEs are sent over traditional HTTP. That means they do not require a special protocol or server implementation to get working. WebSockets on the other hand, require full-duplex connections and new Web Socket servers to handle the protocol. In addition, Server-Sent Events have a variety of features that WebSockets lack by design such as automatic reconnection, event IDs, and the ability to send arbitrary events.

NB: SSE is not supported in IE and Edge. There is a polyfill for this: EventSource.js

WebSockets

WebSockets is a bidirectional communication technology for web apps to asynchronously communicate with a server.

They provide a richer protocol to perform bi-directional, full-duplex communication. Having a two-way channel is more attractive for things like games, messaging apps, and for cases where you need near real-time updates in both directions.

Unrelated similar sounding technologies

There are so many different technologies you can use and each technology is referred to by different names in different sources. Here is a list of technologies completely unrelated to offline web apps and storage, but with similar sounding names. Just to clear things up :-)

 

Web Workers

The Web Workers API is a method of running scripts in the background, isolated from the web page. There are two types of Web Workers: Dedicated, and Shared. Shared Web Workers (a method of allowing multiple scripts to communicate with a single web worker) are not supported in Edge or Safari. All major browsers do support Dedicated Web Workers.

about the author

Finne Fortuin is Drupal development and deployment configuration expert. He also dabbles in JavaScript and offline (game) applications.

Finne