Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with:

Pages Cached By The Cache Manifest Do Not Need To Reference The Cache Manifest

By Ben Nadel on

In last night's post, I discovered that non-cached pages could not make use of resources cached within the application cache. As I was experimenting with that concept, I found that when I added a cache manifest reference to the non-cached page, it both became cached and was granted access to the other cached resources. This is, of course, the expected behavior and exactly what I covered in an earlier cache manifest exploration; but, the question then rose in my mind: is it the cached status or the cache manifest reference that gives one page access to other resources stored in the application cache?

 
 
 
 
 
 
 
 
 
 

After some quick testing, the answer to this question is: cached pages do have access to the entire set of cached resources regardless of whether or not the given page makes any reference to the cache manifest. In other words, it doesn't matter how a page gets cached; but once it does, it has full access to the offline application cache.

To test this, I took yesterday's experiment and simply added the main testing page (index.cfm) to the cache manifest file. Then, as before, I had the "cacher" page reference the cache manifest while the main page remained a standard HTML page:

Cache Manifest (cache_manifest.cfm)

  • <!---
  • Define the Cache Manifest content. I'm doing it this way since
  • the "CACHE MANIFEST" line needs to be the first line in the file
  • and storing it in a buffer allows us to TRIM later without having
  • ugly line breaks.
  • --->
  • <cfsavecontent variable="cacheManifest">
  •  
  • <!---
  • NOTE: Cache Manifest must be the very first thing in this
  • manifest file.
  • --->
  • CACHE MANIFEST
  •  
  • <!---
  • When a cache manifest is reviewed by the browser, it uses a
  • complete byte-wise comparison. As such, we can use COMMENTS
  • to defunk a previously used cache manifest. In this way, we
  • can use a version-comment to indicate change even when the
  • file list has not changed.
  •  
  • NOTE: If ANY part of this file is different from the previous
  • cache manifest, ALL of the files are re-downloaded.
  • --->
  • # Cache Manifest Version: 1.8
  •  
  • # Cache the main page - note that the main page does not, iteself,
  • # have any reference to the cache manifest. It is only be cached
  • # by proxy of the "cacher" page.
  •  
  • ./index.cfm
  •  
  • # Images that get viewed.
  •  
  • ./images/1.jpg
  • ./images/2.jpg
  • ./images/3.jpg
  • ./images/4.jpg
  • ./images/5.jpg
  •  
  • </cfsavecontent>
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!---
  • Let's reset the output and set the appropriate content type.
  • It is critical that the manifest file be served up as a type
  • "text/cache-manifest" mime-type.
  •  
  • NOTE: We need to be careful about the whitespace here since
  • the very first line of the file must contain the phrase,
  • "CACHE MANIFEST". As such, we must TRIM() the content.
  • --->
  • <cfcontent
  • type="text/cache-manifest"
  • variable="#toBinary( toBase64( trim( cacheManifest ) ) )#"
  • />

As you can see, all I did here was add the "index.cfm" relative URL as a line item within the cache manifest. Then, I had the "cacher" page link to this cache manifest:

Cacher (cacher.cfm)

  • <!---
  • Use the HTML5 doc type and provide a link to the Cache
  • Manifest file for this application.
  • --->
  • <!DOCTYPE HTML>
  • <html manifest="./cache_manifest.cfm">
  • <head>
  • <title>I Am The Cacher!</title>
  • </head>
  • <body>
  •  
  • <h1>
  • I Am The Cacher!
  • </h1>
  •  
  • <p>
  • All I do is define a link to the cache manifest that will
  • server to cache the image assets of the application.
  • </p>
  •  
  • <cfoutput>
  • <p>
  • Now: #timeFormat( now(), "hh:mm:ss TT" )#
  • </p>
  • </cfoutput>
  •  
  • </body>
  • </html>

Again, the only job of this page was to make a reference to the cache manifest such that the server would create the offline application cache and proceed to cache each file listed in the manifest. I needed to create this cache by proxy since I wanted to see whether or not the cache manifest reference was required in the main page (index.cfm).

Once I had my cache manifest and my "cacher" page set up, the main page was able to remain as-is:

Main Page (index.cfm)

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>Cache Manifest Test For Pages Cached By Proxy</title>
  • </head>
  • <body>
  •  
  • <h1>
  • Cache Manifest Test For Pages Cached By Proxy
  • </h1>
  •  
  • <h3>
  • Pictures of Alisha Morrow
  • </h3>
  •  
  • <form>
  •  
  • <p>
  • <select id="pictureList">
  • <option value="0">- -</option>
  • <option value="1">Image 1</option>
  • <option value="2">Image 2</option>
  • <option value="3">Image 3</option>
  • <option value="4">Image 4</option>
  • <option value="5">Image 5</option>
  • </select>
  • </p>
  •  
  • <p>
  • <img id="viewImage" src="about:blank" width="300" />
  • </p>
  •  
  • </form>
  •  
  • <script type="text/javascript">
  •  
  • // Get the DOM references.
  • var pictureList = document.getElementById( "pictureList" );
  • var viewImage = document.getElementById( "viewImage" );
  •  
  • // Bind the change method on the select.
  • pictureList.onchange = function( event ){
  • viewImage.src = ("./images/" + this.value + ".jpg");
  • };
  •  
  • </script>
  •  
  • </body>
  • </html>

As you can see, while this page has an HTML5 doc type, it makes no reference to the cache manifest. In fact, this page is not even cached until I execute the "cacher" page which initializes and populates the offline cache. However, once the "cacher" page is requested, and the cache is created, this main page is able to successfully access the images stored in the offline cache.

So, based on last nights post, we can see that non-cached pages cannot access resources in the offline cache; however, once a page does become cached, regardless of the means by which it became cached (through direct reference or by proxy), that cached page then has access to entire offline application cache. Again, this is something that might be pretty obvious; but when you live in the client-server world, the concept of persisted client caching raises a lot of questions!




Reader Comments

I've been reading through your posts on the application cache looking for a solution to recent iphone 4s problem. As I've read, pages that reference a manifest file are also cached themselves. This hasn't been my experience with pre IOS5 iphones. I was able to call a .manifest file in a .cfm file, with the manifest loading jquery, .js, and .css files but still calling the parent .cfm each time so session variables could be accessed. Now, after the switch to ios5, all the iphone 4s' ignore the .cfm (used the cached version) as some have said.

Seems like I am at a crossroads - use the application cache to speed up the web app or ditch it to retain some server side processing. Luckily, the session variables referenced in the CFM are notifications and debugging info so the app. continues to run but this will spur my move to Appcelerator.com or Corona so there are fewer hoops to jump through.

Thanks for your work Ben. You and Ray are always the go to guys for info.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.