Tips when using Application Cache

The following list covers best practice and tips to help reduce many of the problems with using the Application Cache as discussed in the previous blog Problems with Application Cache.

  • Update Notification - The Double Refresh Issue, as described in Problems with Application Cache, means that updates are only viewed when the page is viewed for the second time after a change. After content has been updated, the next time a user views the page they will view the old content loaded from the Application Cache. In the background the Application Cache will be updated and will receive the updated content. The second time a user views the page they will see the updated content. To reduce the impact of this problem it is possible to use the Application Cache API to prompt the user to refresh the page if the Application Cache has been updated. The code to do this is as follows:
  • iFrame Injection - Adding the manifest file to an HTML page adds the HTML to the Application Cache. If your HTML is dynamic but your css, images and JavaScript are static (or fairly static), it is not possible to use the Application Cache by adding a manifest file to your HTML page. In addition once a manifest file is added to an HTML file it forces all files listed in the manifest file to be downloaded synchronously. Files that may not be required initially, such as JavaScript or an image below the fold, will be downloaded at the start of the page potentially delaying the download of more visible resources. The solution to this is to load the Application Cache from a simple HTML file loaded in an iframe. This not only avoids caching dynamic HTML but also avoids the Application Cache being downloaded asynchronously after the page load has completed. The code for this is as follows:
  • Resource Order (css, img, js) - If a manifest file is added to an HTML file, it forces all files to be downloaded synchronously as soon as the manifest file is downloaded. Therefore, files that may not yet be required, such as JavaScript or an image below the fold, will be downloaded at the start of the page. This therefore means it is harder to control the order of downloaded resources on your page. This is particularly problematic for sites that want to download JavaScript asynchronously to ensure that it does not impact the downloading of visible page elements. In addition if a site developer wanted to delay the download of images that are not initially visible then it would not be possible to add these to the manifest file. If they were added to the manifest file they would be downloaded at the start of the page as soon as the manifest file was downloaded. The best way to reduce the impact of this problem is to carefully order the files listed in the manifest file. As a general rule the files should be in the following order CSS -> IMG -> JS. Therefore the CSS, which should always be downloaded at the start of the page, is downloaded first in the Application Cache. Next the images are downloaded maximising the apparent download speed and encouraging users to start interacting with the page as soon as possible. The JavaScript is downloaded last to ensure downloading of HTML, CSS or images is not impacted. If the site is written in a progressively enhanced manner so that it can function without JavaScript, which is strongly recommended, there should be no rush to download JavaScript. This is because JavaScript will only improve the usability and / or performance and the site should function completely without any JavaScript. A future blog will cover more details about this.
  • Use An Open Manifest File - The manifest file can be used to limit the resources which can be downloaded for a page. If a "closed" manifest file is used, then only those resources listed in the manifest file can be downloaded, any other resource can not be downloaded as part of any page the manifest file is attached to. The NETWORK section (as described in How to use ApplicationCache?) contains a list of resources that can be loaded from the network (if available). To indicate the manifest file allows any resource to be downloaded add a * to the NETWORK section. A * indicates an "open" manifest file allowing any resource not listed to be downloaded as required. If the manifest file was "closed" and did not have a * then any resource not listed in either the NETWORK section or the CACHE section would not be downloaded at all. A "closed" manifest file is typically an additional source of bugs. This is because any new resource added must also be listed in the manifest file otherwise it can't be downloaded. Hence, I recommend using an "open" manifest file by adding the * in a NETWORK section.
  • Prevent Manifest File Caching - It is important to prevent the manifest file from being cached. If the manifest file is cached then updating the manifest file on the server will not cause the Application Cache to be reloaded. This is because the browser will receive a copy of the cached manifest file prior to the update. To avoid caching the manifest file ensure the web server serves adds the headers Cache-Control: no-store, no-cache and Expires: 0. Note: Cache-Control: max-age=0 does not prevent caching, instead the max-age value controls the freshness of the resource. The browser will attempt to display the freshest copy possible. If the resource cannot be loaded from the original server (web server) then it may use a stale copy from its local Browser Cache. Using Cache-Control: no-store, no-cache will prevent any copy being kept locally in the cache and will ensure that updates to the manifest file get correctly propagated out to any browser.
  • Version Comment - Once a resource is cached, the browser will continue to show the cached version, even if you change the resource on the web server. Any change in the manifest file, including in a commented line, will cause the entire cache to be updated. I recommend adding a comment with a version number that can be easily updated every time any resource in the manifest file is required to be updated. A common effective version number is a build number as this get automatically updated when a new build is deployed to the web server. A # symbol at the start of the line makes a line into a comment.