Blogs

About this blog

This community site is for software developers interested in topics related to Web 2.0 and mobile device user interface development. This includes both general trends and technology discussions, as well as specific discussions and other resources involv

Tags

Recent tweets

Enable HTML5 Offline Web Application with Dojo 1.7

HTML5 offline web application is a wonderful technology that let web applications work without network connection, which is especially useful for mobile web applications since wireless network is not as stable as wire network is.

According to W3C specification of offline web application, developers needs to provide a manifest file if they want to enable the offline cache capability. The manifest file lists all the resources that will be offline cached and needs to be referenced in HTML page like this. <html manifest=”cache.appcache”>The cache.appcache needs to be served as “text/cache-manifest” content-type and the browser will fetch all of the resource files in the manifest during the first load or whenever the content of manifest is updated.

When the network is unavailable, the browser will detect cache error when trying to communicate with server for the latest manifest and then fetch the resources on the manifest list from local offline cache.

Problem

However, if you are developing a web application with offline capability in the coming Dojo 1.7 (either from scratch or migrated from previous version), you might meet with XHR errors when loading the application in offline mode in Safari mobile on iOS (or maybe in other mobile browsers as well). That is because of:1. By default in Dojo 1.7, the loader is not in true asynchronous mode and will use XHR to load resources2. The XHR loading and offline cache manifest detection are in parallel in Safari mobile, and JavaScript codes are loaded and being executed during the manifest detection.3. In Safari mobile, the XHR sent before manifest detection is completed will not fall back to offline cache. So the request is sent to network, and thus will fail in loading. That's why you get XHR errors even if the target resources are defined in offline cache manifest and preserved in local.

The content of cache.appcache manifest file is very simple. You can get the latest build version from http://archive.dojotoolkit.org. By September 1st, the nightly build can still re-produce the problem.

Below is the content of “cache.appcache” manifest file which just includes some basic resource files.

CACHE MANIFEST

CACHE:test.htmldojo/dojo.jsdojo/selector/acme.js

NETWORK:*

Here is the steps for trying the test in offline mode.

First, let us load the test page in Safari mobile. The author is using an iPhone with iOS 4.3.1. This step allow the browser to load the web resources and cache them in offline cache.

As you can see in Figure 1, the XHR error happens before cache “checking” event is popped up, which means an XHR is sent before manifest detection is completed. That XHR is sent when dojo.js is being executed and it will fetch acme.js.

However, the same test case will not fail on the desktop browser like Chrome. Below is a network log captured in Chrome desktop. It might be because the Chrome browser organize the resource loading after the manifest detection is over or it is much faster for desktop browser to finish the manifest detection than the mobile browsers do. Anyway, the network log in Figure 1 proves that an XHR request for acme.js is sent when executing dojo.js, which fail in Safari mobile.

Figure 2

Solution

So how can we we enable HTML5 offline web application with Dojo 1.7?

The solution is to use asynchronous module loading and honor the web browser in loading resources. Asynchronous module loading will insert <script> tags in HTML document to load modules, instead of sending XHR. That means that the loader delegate the resource loading to web browser and Safari mobile will take the responsibility of loading the content in <script> tag. In this way, Safari mobile can decide the loading sequence, load resources after the manifest detection is over, and prevent any loading conflict.

To enable asynchronous module loading, you have to set “async:true” in djConfig, like below:<script src=”dojo/dojo.js” djConfig=”asyn:true”></script>And you need to follow AMD and use “require()”to load all other Dojo modules or JavaScript files instead of manually coding the <script> tag directly into HTML. For example, if I need to load my own src.js (src.js needs to use AMD way to define the module) which is under the same directory with index.html. I can use the this piece of code right after <script> tag which load dojo.js<script> require([“./src.js”], function (moduleName){ //call back to execute after src.js is loaded });</script>

After the above changes are applied to the code, the test case can now work on safari mobile in offline mode.

Here is the screen capture of the safari mobile log.

Figure 3

Note: the cache error log on Line 9 in the screen capture (Figure 3) means the browser cannot get any update information in the checking of manifest file from the server, it will then force to use the resources in the local offline cache. It is not the error thrown by the browser and is different from the JavaScript error in Figure 1.