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 the jQuery Conference 2010 (Boston, MA) with:

Non-Cached Pages Cannot Access Resources Cached In The Cache Manifest

Posted by Ben Nadel

In my previous post on HTML5's Cache Manifest, Ray Camden and I got into a great discussion about how pages would interact with resources cached by the Cache Manifest file. I was explaining to him that in my experience, any file that linked to the cache manifest was itself automatically cached even if it (the calling page) was not explicitly defined as a line item within the cache manifest. This begged the question: can non-cached pages take advantage of resources otherwise available in the application cache?

Answering this question was not easy at all and took a lot of jumping back and forth between standard and offline work mode in FireFox. After a bunch of playing around, toggling between modes, and clearing caches, I have come to the conclusion that, at least in FireFox, non-cached pages cannot access resources stored offline within the application cache. To see this in action, take a look at the following video:

 
 
 
 
 
 
 
 
 
 

I know I was jumping around in that video quite quickly, so I'm going to reproduce the code below. I won't go into too much detail here as to what it's all doing as this was more about a functional test than an explanation. That said, here is the main test page - notice that it is a standard HTML page that makes no reference to any offline cache manifest.

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>Cache Manifest Test For Non-Cache Pages</title>
  • </head>
  • <body>
  •  
  • <h1>
  • Cache Manifest Test For Non-Cache Pages
  • </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>

Because the above page was not cached in any way, I did need to create a page that referenced the cache manifest and therefore created the offline application cache. This page was the second tab I had opened in my FireFox demo:

  • <!---
  • 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>

As you can see in the above markup, this page makes use of the HTML5 doctype and the cache manifest. The cache manifest that it linked to is defined here:

  • <!---
  • 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
  •  
  • # 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, the cache manifest is only caching the 5 images. So, unless I am missing something critical here in this exploration, what I am seeing is that non-cached pages are not able to access resources cached in the offline application cache by the cache manifest.




Reader Comments

Ok - I think I have a disconnect here. Your cache manifest lists ONLY the images. It doesn't list your root HTML page. If you had selected Work Offline and tried to reload the html page itself, would it have worked? You only tried loading the images, not the page itself. I think the page would not have loaded since it wasn't in the cache manifest.

It sounds like your saying when you added the "manifest" to the html tag, you added THAT page to the cache. I don't believe it is. It's just the images.

Does that make sense? Am I being too picky? Shoot - does it even matter really. If the page itself is what you save to your mobile device, then you wouldn't need a web connection to run it. (Or would you - it should be easy enough to test on the iPhone - just put it in airplane mode.)

Reply to this Comment

@Raymond,

If I had refreshed the page, the browser would have tried to pull the page from the Disk cache (the standard cache). However, I was clearing the Disk cache before interacting with the images; as such, the only copy was the one in the actually rendered in browser at that very moment.

I hadn't thought of trying to cache the primary page from within the cache manifest by way of the "cacher" page. I assume that at that point, this would have worked. I'll give that a quick try when I get to the office in the morning.

As you say though, does it really matter? In general, I would say that it doesn't. But, this brings us back to the question - if I have a main page that is a CFM page that needs to be dynamic, can it operate AND leverage the speed / connectivity advantages of an offline cache? That is a very very specific use case. At the end of the day, if you're gonna cache something on the phone (as you point out), it needs to be cached... period :)

In any case, it's interesting to see how these features interact.

Reply to this Comment

I like to share some points regarding cache Manifest. I came across strange behavior.

I have created an html file with manifest feature and other details mentioned.

I have specified files that to be cached in .manifest file and not specified an image in manifest file.

In online mode every images displayed properly.
In offline mode the file that was not specified in manifest was not be shown in the page.

That was ok

Again i switched back to online mode, but still the image was missing, i tried to clear browser cache but still the same.

I'm not aware of the problem

Could you please provide more details on how manifest works, how it affects online and offline mode

Reply to this Comment

@Thomas,

Now that is an interesting problem. What browser are you using? I am not sure that I have seen that problem personally (but I don't know if I have had that scenario before).

Reply to this Comment

I have been using chrome also i have tested in chrome.

I have added

AddType text/cache-manifest .manifest
ExpiresActive On
ExpiresDefault "access"

to apache server.

Is there any simple method to know if that mime type is working in a server.

I'm not sure about the problem, is it because of caching?

Reply to this Comment

According to Google, I the only person in the world getting a "Firefox is currently in offline mode and can't browse the Web." when I try to view my local would-be offline apps in FF when in offline mode?? My app runs fine in IE9's offline mode but FF just won't and Safari apparently has no offline mode. Fiddler is not even showing FF request the manifest though IE does. What AM I missing?

Reply to this Comment

@Marc,

If you go to "about:cache" in your FireFox browser, you should be able to examine the offline cache. Double-check to make sure that the files you think are cached are actually there?

Reply to this Comment

@Ben, YouDaMan! I had cache disabled in FireBug. I'm so used to IE's developer toolbar...

Reply to this Comment

@Marc,

Awesome - sometimes you just need a second pair of eye to provide a little sanity check :)

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.