offline web applications

The network is a key component of any web application, whether it is used to download JavaScript, CSS, and HTML source files and accompanying resources (images, videos, …) or to reach web services (XMLHttpRequest and <forms>).

Yet having offline support for web applications can be very useful to users. Imagine, for example, a webmail application that allows users to read emails already in their inbox and write new messages even when they are not connected.

The mechanism used to support offline web applications can also be used to improve an application’s performance by storing data in the cache or to make data persistent between user sessions and when reloading and restoring pages.

Demo: a To Do List Manager

To see an offline web application in action, watch Vivien Nicolas’ demo (OGV, MP4), which shows a to do list manager working online and offline on an N900 running Firefox.

You can also check out the live demo of the application.

Creating your Own Offline Application

For a web application to work offline, you need to consider three things:

Let’s see how to use each of these components.

Storage: Persistent Data

DOM storage lets you store data between browser sessions, share data between tabs and prevent data loss (for example from page reloads or browser restarts). The data are stored as strings (for example a JSONified JavaScript object) in a Storage object.

There are two kinds of storage global objects: sessionStorage and localStorage.

  • sessionStorage maintains a storage area that’s available for the duration of the page session. A page session lasts for as long as the browser is open and survives over page reloads and restores. Opening a page in a new tab or window causes a new session to be initiated.
  • localStorage maintains a storage area that can be used to hold data over a long period of time (e.g. over multiple pages and browser sessions). It’s not destroyed when the user closes the browser or switches off the computer.

Both localStorage and sessionStorage use the following API:

window.localStorage and window.sessionStorage {
  long length; // Number of items stored
  string key(long index); // Name of the key at index
  string getItem(string key); // Get value of the key
  void setItem(string key, string data); // Add a new key with value data
  void removeItem(string key); // Remove the item key
  void clear(); // Clear the storage
};

Here is an example showing how to store and how to read a string:

// save the string
function saveStatusLocally(txt) {
  window.localStorage.setItem("status", txt);
}

// read the string
function readStatus() {
   return window.localStorage.getItem("status");
}

Note that the storage properties are limited to an HTML5 origin (scheme + hostname + non-standard port). This means that window.localStorage from http://foo.com is a different instance of window.localStorage from http://bar.com. For example, http://google.com can’t access the storage of http://yahoo.com.

Are We Offline?

Before storing data, you may want to know if the user is online or not. This can be useful, for example, to decide whether to store a value locally (client side) or to send it to the server.

Check if the user is online with the navigator.onLine property.
In addition, you can be notified of any connectivity changes by listening to the online and offline events of the window element.

Here is a very simple piece of JavaScript code, which sends your status to a server (à la twitter).

  • If you set your status and you’re online, it sends the status.
  • If you set your status and you’re offline, it stores your status.
  • If you go online and have a stored status, it sends the stored status.
  • If you load the page, are online, and have a stored status, it sends the stored status.
function whatIsYourCurrentStatus() {
  var status = window.prompt("What is your current status?");
  if (!status) return;
  if (navigator.onLine) {
    sendToServer(status);
  } else {
    saveStatusLocally(status);
  }
}

function sendLocalStatus() {
  var status = readStatus();
  if (status) {
    sendToServer(status);
    window.localStorage.removeItem("status");
  }
}


window.addEventListener("load", function() {
   if (navigator.onLine) {
     sendLocalStatus();
   }
}, true);

window.addEventListener("online", function() {
  sendLocalStatus();
}, true);

window.addEventListener("offline", function() {
  alert("You're now offline. If you update your status, it will be sent when you go back online");
}, true);

Offline Resources: the Cache Manifest

When offline, a user’s browser can’t reach the server to get any files that might be needed. You can’t always count on the browser’s cache to include the needed resources because the user may have cleared the cache, for example. This is why you need to define explicitly which files must be stored so that all needed files and resources are available when the user goes offline: HTML, CSS, JavaScript files, and other resources like images and video.

The manifest file is specified in the HTML and contains the explicit list of files that should be cached for offline use by the application.


Here is an example of the contents of a manifest file:

CACHE MANIFEST
fonts/MarketingScript.ttf
css/main.css
css/fonts.css
img/face.gif
js/main.js
index.xhtml

The MIME-Type type of the manifest file must be: text/cache-manifest.

See the documentation for more details on the manifest file format and cache behavior.

Summary

The key components you should remember to think about when making your application work offline are to store the user inputs in localStorage, create a cache manifest file, and monitor connection changes.

Visit the Mozilla Developer Center for the complete documentation.

About Paul Rouget

Paul is a Firefox developer.

More articles by Paul Rouget…


34 comments

  1. Paul Rouget

    One more thing:
    We talked about local/sessionStorage. We don’t support any databaseStorage *yet* (like Webkit does with sqlite), because we felt that we need something different, simpler (the indexed sequential storage API edited by Oracle’s Nikunj Mehta). See more details here: http://us1.campaign-archive.com/?u=168bf22f976f5a68fe5770d19&id=6c2d73c957#standards

    January 7th, 2010 at 12:45

  2. Chris

    Awesome i wish all browsers will support this quickly :)

    January 7th, 2010 at 21:49

  3. Eevee

    I miss the days when running a program and reading files without the Internet wasn’t an impressive technical feat. :(

    January 7th, 2010 at 22:33

    1. zahra

      me too

      January 12th, 2011 at 08:02

  4. frank goossens

    the lack of ‘structured’ storage in firefox -however correct the reasoning behind not wanting to do databasestorage with sqlite- is frustrating, especially since chrome and opera are expected to provide webdb-support. is there any roadmap for inclusion of the “indexed sequential storage API” in FF?

    that being said; the biggest problem for offline apps is cross-browser compatibility. i’ve been hacking on a cross-browser offline-enabled web application that can store data in a structured manner, using persistjs (a javascript library which abstracts access to localstorage, webdb, ie userdata behaviors, gears, flash, …) to store json-ified arrays/ objects, and application caching (using both html5’s and gears localserver). you can see the result, TrappistDB, here.

    January 8th, 2010 at 00:33

  5. Jon Rimmer

    Isn’t there a problem with the design of localStorage? I’ve read some stuff suggesting that it’s not possible to implement the current spec in a performant way on multi-process browsers. What’s the latest on that?

    January 8th, 2010 at 03:23

  6. matt

    Great to know in these early days of unreliable Cloud

    January 8th, 2010 at 04:51

  7. Natanael L

    It would be nice if big files could be shared using torrents, such as on YouTube :)

    January 8th, 2010 at 06:30

  8. Cedric Dugas

    I wish browser vendors could implement the same database storage…. its going to be a mess to get it work on safari and firefox..

    January 8th, 2010 at 08:33

  9. […] Hacks desarrolla una aplicación a modo de demostración que nos permite disponer de una lista de tareas alojada en nuestro navegador, podéis verla […]

    January 8th, 2010 at 17:10

  10. […] Hacks desarrolla una aplicación a modo de demostración que nos permite disponer de una lista de tareas alojada en nuestro navegador, podéis verla […]

    January 8th, 2010 at 18:01

  11. nemo

    Cedric, localstorage works in webkit and IE8 too.
    Until the sqlite thing is ironed out, seems best to just use that. Isn’t that much of a mess.

    And even after you can finally do sql queries in firefox and safari, you’ll probably still have to wait for IE.

    January 9th, 2010 at 20:11

  12. yannski

    One of the top thing our users wanted out of our offline app (we develop a small Product Lifecycle Management tool) is the ability to have feedback from the sync process, like “downloading 3 / 325 documents”. It was not possible at the beginning with Gears, but they eventually got it. Now, it seems that the native offline “mode” in FF cannot do the same. Or I didnd’t found the right documentation for the applicationCache javascript object… For example, I cannot access the “items” attribute described in https://developer.mozilla.org/en/nsIDOMOfflineResourceList

    Maybe you could give some pointers…

    January 12th, 2010 at 07:11

  13. Paul Rouget

    @yannski The MDC API is wrong. The “moz” prefix is missing (mozItem for instance). We will fix that asap.

    You can check the correct API here:
    http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/offline/nsIDOMOfflineResourceList.idl

    January 15th, 2010 at 08:05

  14. yannski

    Well, with Firefox 3.5, window.applicationCache.mozItems seems to be always empty (or I don’t understand how to use it). Some code sample would be great…

    January 17th, 2010 at 15:44

  15. Pete

    Webkit like databse storage is available with https://addons.mozilla.org/de/firefox/addon/70769

    February 18th, 2010 at 12:50

  16. Aris Micro

    But localStorage doesn’t work if you use the file:// scheme (instead of http://) i.e. if you are offline and double-click on a local .html file.

    February 21st, 2010 at 18:49

  17. Omkar Kandarpa

    Hi,

    You can access the current status of caching, along with pending files count using downloading,progress events of applicationCache object.

    June 1st, 2010 at 01:21

  18. […] offline web applications, 2010년 1월 7일, Paul […]

    June 30th, 2010 at 18:32

  19. […] HTML5 Application Cache: 이것은 브라우저가 인터넷에 연결되어 있지 않을 때에도 사용할 수 있는 어플리케이션을 작성하게 해준다. 이것은 어플리키에션 전체를 브라우저내에 저장하고 온라인과 오프라인 이벤트에 대한 접근을 제공함으로써 어플리케이션이 언제 서버와 다시 동기화해야 할지를 알 수 있게해준다. […]

    July 7th, 2010 at 09:22

  20. Patrick

    Consider impel ORM for HTML5 databases (http://impel.simulacre.org/).

    July 28th, 2010 at 04:49

  21. Günter

    Started to write an ICS/iCal ‘app’ to be used in local browser mode only and also with the goal to use only HTML/CSS/JS.
    This requires access to ics files stored with the local file system (also to use it with other applications like Lightning, etc).

    At the moment for local storage access I’m using jQuery.twFile.js which basically uses some Moz Components.classes.
    How to change that concept to use HTML5 storage so it can be used with any HTML5 platform?
    Any pointer for further info / discuss?

    October 31st, 2010 at 05:28

  22. Pedro Morais

    I’ve written a blog post about how we made our time tracking webapp work offline.
    Might be useful as it is a real life example:
    http://blog.bitrzr.com/2010/10/html5-offline-webapps-practical-example.html

    November 28th, 2010 at 09:38

  23. Mani

    Maybe a good article, I dont know… I got irritated after seeing a video downloading and I had no way of stopping it. And I know that I am paying for that bandwidth and helplessly watched the video loading.

    Probably a HTML5 downside – we have to stop the video from downloading if we are on an expensive data plan. Now I need to get a plugin to block html5 video. In future, we are going to see ads invariably loading and eating away bandwidth, flashblock used to be so good.

    To the author: cant you think from your visitor’s point of view ever, before posting that stupid HTML5 video from auto loading???? Not everyone visits your page from their unlimited home broadband.

    May 22nd, 2011 at 20:49

    1. louisremi

      You can open about:config in your browser, read the warning message and accept it, then right-click anywhere in the list, “New” > “Integer”
      Then give the preference the name “media.preload.default” and choose 1 as the value.
      Repeat with the name “media.preload.auto” and choose 2 as the value
      You’re done :-)

      May 23rd, 2011 at 08:42

      1. Mani

        Amazing, thanks a lot !!!

        I take back my original comment, it was unnecessary, I should have explored before posting. Sorry about it.

        Do you know any similar method for google chrome? Anyways, firefox is going to be my default till I find something for chrome.

        Thanks again :-)

        May 23rd, 2011 at 08:54

  24. […] http://hacks.mozilla.org/2010/01/offline-web-applications/ […]

    June 2nd, 2011 at 00:45

  25. […] Mozilla Hacks: 离线网页应用程序 […]

    June 19th, 2011 at 22:06

  26. […] Mozilla Hacks: Offline Web Applications […]

    July 10th, 2011 at 06:12

  27. […] SitePointStandardists Estelle Weyl’s take on offline web appsMore fromthe folks at Mozilla on building offline web appsOpera Developers Network on building offline web apps.Critiques and gotchasas we know, all is not […]

    July 11th, 2011 at 04:05

  28. […] More fromthe folks at Mozilla on building offline web apps […]

    July 19th, 2011 at 12:57

  29. […] Mozilla Hacks: 离线网页应用程序 […]

    August 23rd, 2011 at 00:53

  30. Yv.R

    Hi, first thks for post. Just ask you few question. I’m making some web app with offline mode and using appcache… it perfectly works with chrome browser or some mobile browser like dolphin.. but still not work for firefox. I started with firefox 3.6.26( used by my clients) and then migrate to the last one 18.0.2 but it still not work. Here are the most important file

    – htaccess
    AddType text/cache-manifest .appcache

    – cache.appcache
    # v3.3..4

    CACHE:

    index.html
    page2.html
    img.png
    off.html

    SETTINGS:
    prefer-online

    FALLBACK:
    / /off.html

    NETWORK:
    *

    – and finally the line within the main file

    Have you ever met this issue?

    February 12th, 2013 at 07:56

    1. IMEVER

      Maybe youy – cache.appcache file shoud begin with “CACHE MANIFEST”

      February 19th, 2013 at 03:04

Comments are closed for this article.