mozilla
Your Search Results

    Letting your app work offline Redirect 1

    Making open web apps functional while offline is an important problem to solve: users may lose network while on the move. In addition, having your files available locally will make your app require less server access and therefore be repsonsive.

    Recommendations

    The following is a set of recommendations and best practices for getting up and running with offline web apps quickly.

    Detecting offline state

    There are a few APIs available to determine the user's connection status. These are useful because you can skip HTTP requests if you know the user is offline. You can also display less generic failure messages. For example: if you were writing a Twitter client, a message like “New tweets cannot be loaded while offline” is more informative than “Could not make HTTP connection.”

    Try to focus on loading data from your/others' API only when needed, and keep data cached so you don't have to request the same data twice. It can also be helpful to prefetch some data so the user can use parts of your app offline that they have yet to open.

    navigatorOnline.onLine is designed to detect online status, but this is not very reliable. There are a number of other offline detection mechanisms, but we would recommend using an offline detection library, such as offline.js.

    If you are using XMLHttpRequest to update data dynamically, you can check its response to determine if the network connection has dropped during the use of your app. If your app has systemXHR privileges, you can check for a connection to a site unlikely to be down to determine if you have an active connection (iOS does this with Apple.com).

    // We'll assume we aren't online.
    var online = false;
    
    // Assume we're a packaged app with systemXHR permissions.
    // https://developer.mozilla.org/docs/Web/Apps/App_permissions
    var request = new window.XMLHttpRequest({mozSystem: true});
    request.open('HEAD', 'http://www.mozilla.org/robots.txt', true);
    request.timeout = 5750;
    
    request.addEventListener('load', function(event) {
       console.log('We seem to be online!', event);
       online = true;
    });
    
    var offlineAlert = function(event) {
       console.log('We are likely offline:', event);
    }
    
    request.addEventListener('error', offlineAlert);
    request.addEventListener('timeout', offlineAlert);
    
    request.send(null);
    

    When your app is first loaded/installed, it should store its assets and data offline, as indicated below. On subsequent loads, it should take a progressive enhancement approach — assume the app is offline and work with the dataset it has available in offline storage. If online, it should update the assets and data as available.

    Storing assets offline

    If you are distributing your app as a packaged app on the app store (for example a Firefox OS app, distributed via the Firefox Marketplace), then you get this part for — once the app is installed on the device, the assets are saved locally (see Packaged apps).

    If your app is hosted and you want it to be available as an open web app as well as installed on Firefox OS, you will need to use App Cache, which is good for most cases, but does have its own problems to be considered and worked through. The AppCache manifest will typically list of all the CSS, fonts, JavaScript, and image files you use. You can use tools to generate your manifest or create one by hand. This is an example of the format, from Face Value’s manifest:

    CACHE MANIFEST
    # v 0.1 / 12
    
    CACHE:
    css/app.css
    img/coins/gold@2x.png
    js/main.js
    js/lib/require.js
    
    NETWORK:
    *
    http://*
    https://*

    Note: If you're using JavaScript templates like mustache, be sure to include your templates in your Appcache manifest or precompile them into your built JavaScript files.

    Important: In your appcache manifest you cannot specify any resources that are on a different domain (even redirects). Chrome lets you do this as long as the resources are served over SSL, but this contravenes the spec, and other browsers don't. Bear this in mind if, for example, you are serving content from a CDN with a different origin.

    Storing data offline

    To get up and running quickly with offline data we'd recommend that you use localForage, 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 (such as Safari), and localStorage for browsers with even more basic support. (see more detailed support info).

    localForage uses simple, localStorage-like syntax for getting and setting data items:

    localforage.getItem('key', function(value) {
            alert('My value is: ' + value);
        });
    }
    localforage.setItem('key', 'value', doSomethingElse);

    Note: For more information, read how to use localForage.

    Note: The Device Storage API is an option available on Firefox OS for storing large data objects, but IndexedDB (localForage) should also be ok. The Podcasts reference app uses IndexedDB to sotre episodes in its episode model code.

    Saving state

    During app usage, you should ensure that its state is saved periodically to the offline data store, and save state locally when user closes the app.

    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. We are working on an easy solution for this.

    Third party code that may help:

    Examples

    TBD

    Tutorials

    If you want more information on how localForage, etc. works behind the scenes, these tutorials should help.

    Reference

    Reference material.

    Document Tags and Contributors

    Contributors to this page: Sheppy, teoli
    Last updated by: teoli,