Experimenting With HTML5's Cache Manifest For Offline Web Applications
After playing with Safari's SQLite support for use with creating client-side databases, I thought I would try looking into HTML5's "Cache Manifest" for creating offline web applications. The Cache Manifest is a text file that lists out all of the application resources that need to be cached in order for the given application to work without an internet connection. The files listed in the cache manifest get stored in the "Application Cache". The Application cache is like the browser's standard disk cache, but much more robust. Once a resource is stored in the application cache, the browser will never request it from the web until the cached item is de-cached or the cache manifest is invalidated.
When it comes to using the cache manifest, I'm less interested in the "offline" aspect of it and more interested in the beasty caching mechanism that comes with it. Once the browsers sees the cache manifest file and gets your approval to create an offline cache, the browser then proceeds to progressively download all cachable items in the background. As such, you can hit your homepage (for example) and end up getting the entire application cached. And, once the application resources are cached, navigating around the application essential becomes a local operation, not a remote one.
To experiment with the HTML5 Cache Manifest, I created a very simple photo gallery page that lists out a few links to view higher resolution photos. Each of the "view" pages is a ColdFusion page that dynamically loads a given photo based on the photo ID. The HTML for the list page is rather straightforward:
<!---
Use an HTML5 doc-type. This is required for some browsers to
work properly with the offline-cache.
--->
<!DOCTYPE HTML>
<!---
Add a file to the cache manifest. NOTE: Any file that calls
a cache manifest file will be automatically cached, even if
it is in the WHITELIST portion of the cache manifest.
--->
<html manifest="./cache_manifest.cfm">
<head>
<title>Cache Manifest For Offline Pages</title>
<!---
These are the two graphics (logo and startup screen) use
for "app mode" on the iPhone (when the web page is put on
the main screen as its own logo).
NOTE: This part has nothing to do with the cache manifest
stuff - this is strictly related to runnin a website in
"App Mode" on an iPhone. Feel free to remove this entirely
from the example.
--->
<link rel="apple-touch-icon" href="icon.png"/>
<link rel="apple-touch-startup-image" href="home.png" />
</head>
<body>
<h1>
Cache Manifest For Offline Pages
</h1>
<h3>
Pictures of Alisha Morrow
</h3>
<ul>
<cfoutput>
<!---
Notice that we are dynamically generating this
page. It will only be generated on the first
request. After that, this page will be coming out
of the cache.
--->
<cfloop
index="pictureIndex"
from="1"
to="5"
step="1">
<li>
<a href="view.cfm?id=#pictureIndex#"
>View Image #pictureIndex#</a>
</li>
</cfloop>
</cfoutput>
</ul>
<p>
Now:
<cfoutput>
#timeFormat( now() , "hh:mm:ss TT" )#
</cfoutput>
</p>
</body>
</html>
When it comes to the cache manifest, there are two crucial things going on here. First, because cache manifest is part of HTML5, we need to use the HTML5 doctype:
<!DOCTYPE HTML>
While this is not required for all browsers (supposedly), it is recommended for cross-browser comparability. The second, and perhaps more important thing that we are doing is including a link to the actual cache manifest file. This link is defined in the HTML tag:
<html manifest="./cache_manifest.cfm">
This file, cache_manifest.cfm, is the file that lists out all of the cachable resources in our application:
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.3
<!---
Let's list the file that get cached. The URLs to these files
are relative to the cache manifest file (or absolute).
--->
# Core files.
./index.cfm
# iPhone App files.
./icon.png
./home.png
# View Pages. Notice that these can be dynamic pages as long
# as they are valid URLs.
./view.cfm?id=1
./view.cfm?id=2
./view.cfm?id=3
./view.cfm?id=4
./view.cfm?id=5
# 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 ) ) )#"
/>
When it comes to the cache manifest, there are few essential points to understand. One, the phrase, "CACHE MANIFEST", must be the very first piece of content in the cache manifest file. Two, the file must be served up as the mime-type, "text/cache-manifest". And three, the entire cache manifest file is versioned by byte. This last point means that if any part of the cache manifest changes, including any of the comments (#), that cache is invalidated. As this point - when the cache is invalidated - the entire list of cachable resources must be downloaded again.
Just as in a CSS file, the resource paths listed in the cache manifest can be full URLs or URLs relative to the location of the cache manifest file. Because we are caching dynamic pages, each "dynamic version" of the page needs to be individually listed out in the cache manifest. There are other ways to do this, but for my experiment, this was the lowest-hanging-fruit solution.
The "view" page that I am linking to does nothing more than take the given ID and dynamically generate an IMG tag.
view.cfm
<!--- Param the image ID that we are going to view. --->
<cfparam name="url.id" type="numeric" />
<!---
Use an HTML5 doc-type. This is required for some browsers to
work properly with the offline-cache.
--->
<!DOCTYPE HTML>
<!---
Add a file to the cache manifest. NOTE: Any file that calls
a cache manifest file will be automatically cached, even if
it is in the WHITELIST portion of the cache manifest.
--->
<html manifest="./cache_manifest.cfm">
<head>
<title>View Image</title>
</head>
<body>
<h1>
View Image
</h1>
<p>
« <a href="./index.cfm">Back to List</a>
</p>
<p>
<cfoutput>
<img src="./images/#url.id#.jpg" width="300" />
</cfoutput>
</p>
</body>
</html>
I am including the cache manifest link in the view page as well; although, I don't believe it is required. As long as a user hits the list page first, the cache manifest will be downloaded and the view pages should be cached automatically. I simply kept it here for good measure.
In the list page, you may have noticed a few bizarre LINK tags. These LINK tags are specific to the Apple iPhone and are used to define the Icon and Startup screen graphics to be used when the web application is running in "App Mode". This is the full-screen mode that can be achieved when the given URL is added to the home screen of the iPhone. These link tags are not relevant to the cache manifest; but, they are indicative of where I want to go with this type of HTML5 exploration - building native-esque web applications for the iPhone.
The cache manifest seems like a very cool feature of HTML5. I was able to get this example running in FireFox, Safari, and on my iPhone (didn't test any other browsers). I didn't do too much with my desktop Safari research, but it was mighty awesome to see this working in Offline mode in FireFox and in Airplane mode on the iPhone. As I have stated before, where I'd like to go with this research ultimately, is building my Dig Deep Fitness web application to run as if it were a native application on the iPhone.
NOTE: When I first started playing around with the cache manifest, I was having the hardest time getting the offline cache to be recognized. For two days I kept checking my spelling and my linking to no avail. Then, I restarted my FireFox and blam - it starts working. So, if this doesn't work right off the bat, you might have to restart your browser.
Want to use code from this post? Check out the license.
Reader Comments
The Manifest is really nice as you can tell the browser to download objects when it does reach the listed content of a website, I am still unsure if this is more of a benefit to those websites that don't turn on headers through IIS/Apache for setting a content expires header.
@Josh,
I think one of the nicest benefits of it is that it will download the given files in the background. As such, you can download and cache files that you have not even been to yet, which is very different than disk cache (which requires a visit first). Also, from what I have read, the SIZE of the cache is very different. Especially on the iPhone, the disk cache is very small, where as the offline cache is much larger.
Speaking of headers, though, what I have seen one person do is actually set an expires header on the cache manifest itself. In this way, the browser doesn't keep trying to check the stored manifest against the life one (as it is explicitly told that the cache manifest won't expire for a given amount of time). So, in that case, it's kind of the best of all worlds.
Thanks Ben. I LOVE what HTML5 and CSS3 are doing to make life easier. Kinda makes the callouses on the fingertips, and forehead bruises a little futile now.. :-)
@Billy,
Ha ha, yeah the CSS3 stuff is especially cool (once you bail on IE6).
This morning, I took this Cache Manifest stuff a bit further and used it to create native-like web applications on the iPhone:
www.bennadel.com/blog/1945-Using-The-Cache-Manifest-With-iPhone-s-App-Mode-For-Native-Web-Applications.htm
A comment about this comment:
Add a file to the cache manifest. NOTE: Any file that calls
a cache manifest file will be automatically cached, even if
it is in the WHITELIST portion of the cache manifest.
That seems problematic. If I want to cache images for example, but not the HTML of a page, it sounds like the second I link to the cache file from index.cfm, then index.cfm ITSELF is cached. Is that right?
@Raymond,
Yes, that's my experience with it. I had a ColdFusion page a while back (when I first looked into this) that needs to do just that - cache the images for a photo library. Unfortunately, the second I started using the cache manifest, the ColdFusion page stopped being dynamic :) So, it kind of defeated the purpose.
Hmm. So forgive me if this is covered - I'm mainly just talking this out to myself.
If I only wanted to cache images - I'd have to at least cache the index page too. And if the index itself was dynamic, I'd want to use a Cache Manifest Version that changed whenever the images changed.
@Raymond,
This is exactly what I was trying to battle. I tried including an IFrame in the index page that linked to a page that did nothing more than include the Manifest directive. I can't remember if that worked or not (part of me feels that it did not).
This raises a great question though, one for clarification. Can a non-cached page make use of any cached items? In other words, does the calling page have to include the cache manifest for it to be able to make use of the application cache?
I guess where I'm going with this is - how does the URL to cached items work? It it *strictly* based on resource URL? Or, is it a combination of resource URL and the calling page?
I'll have to play around with that a bit to see what kind of functionality I can get in offline mode in FireFox. Good food for thought!
I would have assumed that if you are on
n.html
and n.html points to a cache file that says urls A+B+C are cached, that n.html need not be cached. But if you click a link to A within n.html, it would use the cached version if offline.
Just guessing.
@Raymond,
I just tried playing around with this non-cached / cached interaction and found some interesting results. At least in "offline" work mode in FireFox, it appears that non-cached pages cannot take advantage of cached images:
www.bennadel.com/blog/1946-Non-Cached-Pages-Cannot-Access-Resources-Cached-In-The-Cache-Manifest.htm
FYI, darn good article on the cache:
http://www.html5rocks.com/tutorials/offline/takingappoffline/
@Raymond,
Oh good link, thanks. I saw that the HTML5Rocks web site was just launched like Monday or something on Twitter but have not had a chance to look through it yet. I am sure it is chock full of goodness :)
Curious about something, Ben: Why the toBinary(toBase64())?
When I saw that, I thought that maybe I had missed something. So I looked through http://developer.apple.com/safari/library/documentation/iphone/conceptual/safarijsdatabaseguide/SafariJSDatabaseGuide.pdf again, and there isn't any mention about the cache manifest being anything but text. Also no mention of making the manifest binary at the http://www.html5rocks.com/tutorials/offline/takingappoffline/ URL that Raymond mentioned. And also nothing at the official http://www.w3.org/TR/offline-webapps/ document.
When you think about it, text/cache-manifest has the primary mime type of text, which would argue that you should not make it binary.
So now I'm more confused than ever.
I have no doubt that you read something somewhere about it that made you want to add toBinary(toBase64()). And from your success with BuffBabes, it apparently works fine. But I'd like to read more about the binary conversion rationale if you have some URLs to quote.
Thanks.
Hi Ben,
Just want to say really enjoying this series on HTML5 features, I'm using them at the same time and you're insights are really helping.
I'm using a dynamic cache.manifest.php file (to add entries for all subfolders/images/css) and I've found it a bit hit and miss as to whether the app displays the new content after updating this file.
Usually it takes at least 30 seconds after I've edited the manifest before I can run the app (from Home Screen icon) and have it display the new content.
Not sure where this arbitrary 30 seconds comes in but as long as it works!
@Steve,
The toBinary() thing has nothing to do with the cache manifest itself. It has to do with the CFContent tag in ColdFusion. It's just my personal preference / style when streaming content back to the client. The CFContent tag has a "Variable" attribute that allows you to pass in a binary data value that will become the response data. As such, I need to convert my respond output to a byte array before I can use it with CFContent.
Again, just my personal preference. And in this case, where the "CACHE MANIFEST" directive needs to be the very first thing in the response, this technique, in combination with trim(), really makes things easier.
@Richard,
I have also experienced the delay in how the updates to the cache manifest affect the update. When testing in FireFox, I typically just clear out the offline store and refresh. In Safari on the iPhone, however, I was finding that it did have a noticeable delay in when the changes were acknowledged.
@Ben, thanks. I'm an Adobe Certified Advanced CF developer, but the binary aspect of the cfcontent variable attribute slipped under my radar. Good to know that you have to call toBase64 too to get it debinarized back to text.
FWIW, I use enablecfoutputonly for the same grabbage strippage. (Sorry. Just got back from Fogo de Chao. Post-huge-meal anemic torpor has me playing fast and loose with whether or not something is really a word.)
@Steve,
Mmmm, Fogo :) It's so good it hurts.
Yeah, the Variable attribute of CFContent I believe is new in CF8. I think I'm pretty much the only person who loves it. I very rarely ever see anyone else use it. I just find it makes tailoring the output much easier since you don't have to think about settings and line breaks.
But of course, to each their own. I happen to love it; but not everyone thinks it's all that.
I think the delay is just to do with how the update works. It updates in the background first, and does not automatically replace the version you're looking it. I've written a bit of code which allows the user to choose to update (this works for the data-entry app I have been working on).
http://pastebin.com/MEuDsaiw
So the update prompt appears if the manifest has changed, and roughty 1 minute or however long the assets take to download. Then they are applied and the page is refreshed.
@Richard,
Cool stuff. I've seen the Javascript hooks in the Cache Manifest documentation but have not looked into them at all. From your code, it looks pretty straightforward. I'll have to play around with it. Thanks for sharing the link.
hi ben,
nice tutorial but i found difficulty in update data with javascript
i found this
window.applicationCache.swapCache();
I try this but still cache data is not updating
do you have any idea?
@Kuldeep,
I haven't actually tried any of the Javascript-based ways of interacting with the offline application cache. When I get to that, I'll see if I can shed more light on the issue.
Hi Ben, having checked all articles on Html5's appCache, is there a solution to just update newer files, using the manifest file? I am looking into using application cache to actually have an offline website running on USB stick which is capable to update itself. But only download the changed or added files?
It seems that AppCache lacks support with this particular matter.
@Ben: According to Mark Pilgrim's O'Reilly book HTML5: Up and Running, pp. 141-142, the window.applicationCache fires a sequence of events: "checking", "downloading", multiple "progress" events, potentially "error" (you hope not), "cached" and in the case of refreshing network files that are newer than cached files, "updateready".
You would call swapCache() in the "updateready" event handler, but if the "error" event occurs, you never get as far as "updateready". So then Mark launches into 2 more pages about how to deal with the debugging problem (figuring out why "error" occurred).
Is that what you guys were wondering?
@Mardy,
From what I remember reading, the caches is completely valid or it is completely invalidated - I don't think there is any in-between (at least not using the cache manifest on its own). To this end, I think people tend to put some sort of comment in the cache manifest that signifies the version of the manifest:
# Cache v6.3
... then they can change the comment to invalidate the entire cache (and re-download every single file in it).
If you want to only download some of the files, I believe you will have to do that with Javascript; though, I have not played with that myself.
That said, I have no idea how the caching of files will interact with the use of a USB stick? Are you using a mobile version of Firefox or something?
@Steve,
Ah, that sounds good - thanks for jumping in on that matter. I haven't looked into the Javascript at all.
Sounds like a good book. I've got it open in another tab- might be ordering that ;)
@Ben: You kinda HAVE to get into the JavaScript eventually, because of the need to save updates for later upload to the server. Basically, there isn't any automatic saving of form contents to local storage, session storage or SQLLite. You have to code a pretty sophisticated onsubmit.
The issue that interests me is the fact that someone else could have altered the server data, so the data you try to upload to the server could overwrite someone else's change.
You're kinda forced to keep all old values and, when you're back online, submit both old and new values to a Web Service in a way that says "If database column x's value is a, change it to b. But if x's value is anything else (say, c), tell me so, and I'll let the user decide whether its value ought to be b or c."
As long as you're coding browser side and server side code of that much complexity, a little appCache management coding doesn't seem like comparatively that big a deal. :-)
@Steve,
Online-Offline data syncing is tremendously fascinating to me right now; this is the one topic that I keep going over in my mind. I really need to do some research on this. I have no idea how people handle this kind of stuff. Just keeping two different sets of unique keys kind of blows my mind.
The place where I really want to understand this is for my Dig Deep Fitness mobile app. I wanted to create a SQLite DB and have a centralized web app online for standard browsers. But, that means that one account can be updated by *multiple* mobile apps which means the syncing has to go both directions (mobile to central / central to mobile).
Arrrrg :D
I feel completely stuck on the topic. I need to find some good tutorials on the matter.
@Ben,
Yes, I am using Firefox Portable. At the moment I run a portable web server on the stick which holds and serves all files. The good thing is, I can run PHP pages on the stick to do requests to the hosted site where all data and updates are beeing handled. And that's where I serve updates in form of a zip file. That gets downloaded, unzipped, deleted, all in PHP.
I have found out that version control is pretty hard to manage. At the moment there are 1500 USB sticks out there, more coming, all updating their offline web files. So I thought appCache would be better to handle, but lacking of what I mentioned earlier, I still don't know.
@Ben: Yeah, I hear you on that topic. We ColdFusion coders have it extra rough, because the contents of the page served up by the server is dependent on context.
So you're a manager and you call up an employee to edit something. It gets cached, but it gets cached in the context of editing that employee. What if you'd like to cache the profiles of your entire staff to work on them over the long weekend? Same page, 10 different contents.
It almost forces you to load up context on the URL (editemp.cfm?EmpNo=3) rather than Session scope. Will having a different URL due to query_string cause them all to be cached separately? I wish I could tell you, but I haven't gotten far enough along to test it yet.
@Mardy,
Sounds like a really cool project you have going on over there. Are you running something like Jetty? I have long wanted to run ColdFusion "anywhere", which was a blog series that I read some years ago; from what I can remember, it ran Jetty as a stand-alone server.
I wish I had more advice to give you this matter but I don't have enough Cache Manifest experience to really point you in any great direction.
@Steve,
From my experience above, it looks like the each page gets downloading according to its query string variables. Whether or not the order of the query string variables matters - I assume it does since the pages seem to be cached strictly on their URL formation.
This weekend, I tried playing around with local/live data synchronization.... wow - that was quite a journey. Several hours later and I have a really complicated single-table example. Hopefully I can post that tomorrow.
@BEN,
I started with a range of open source portable servers, but they all lacked support of customisation. So I found DWebPro, a commercial product which supports serveral server sides and ColdFusion as well. If you are interrested, look into that. It costs a bit of coins, but it is very flexible and they have a great support team.
@Mardy,
That looks really cool; and, you can download a free version for personal use. I'll have to check that one out. Thanks for the tip.
@Ben, no worries mate!
Yes, you can download a fully functional free version to run your tests, the only thing you can't do, is change your startup image, otherwise it is fully functional. Check out their download section to add ColdFusion, PHP or other stuff.
@Ben: Thanks! It's already posted. Can't wait to read it.
P.S.: There's now a 3rd book. My theory that Bruce and Remy's book getting released forced Mark's book to get released seems to be holding water. Now Peter Lubbers' book "Pro HTML5 Programming" just shipped.
@Mardy,
I can live with a "ad" startup image for testing. I just can't wait to try it out.
@Steve,
I just ordered a book from the List Apart people (A Book Apart). I can't remember what the book is, but it was something like HTML5 For Designers or something. Gotta stock up on good HTML5 books.
@Ben,
Haven't heard of any with "for Designers" in the book title, but Remy Sharp has a site called "jQuery for Designers" and he the first book I told you about (Introducing HTML5 (Voices that Matter)).
It's about 1 AM and I'm still at work. I've been working on Section 508 compliance (accessibility) using HTML5 technologies. I had a bar graph Java applet that graphed statistics from a database query, but of course screen readers can't read it. I just now finished converting the code to canvas (also not readable, but more widely supported than Java applets nowadays) and Inline SVG (readable by screen readers, yay!).
Only Firefox 4.0 Beta supports SVG that's coded inline. Some will support SVG that enters the page as an img tag, but inline is the way that's accessible to screen readers. Only MSIE doesn't support canvas.
... and he coauthored the first book ...
Sheesh.
@Steve,
1AM? Bro, you have got to take it easy :) You don't want to burn out. 508 Compliance is an interesting issue, legally speaking. At CFUNITED this past August, I went to a talk about 508 CSS/HTML by Sandy Clark. Definitely a good talk and one that seems to have real legal ramifications in the near future.
Anyway, the book I was referring to was this: http://books.alistapart.com - HTML5 for Web Designers. It supposed to be leass than 100 pages, so a quick read. I'm looking forward to getting the books you recommended as well.
@Ben,
Thanks for the URL! When this is over, I'll have at least 5 HTML5 books, 3 of which are in my possession now. (The Lubbers book arrived yesterday. It focuses on the extra nerdy stuff: web sockets, web workers, geolocation, client-side SQL, etc.) The HTML5 presentation (by Scott Stewart of Fig Leaf I told you about earlier) opened my eyes to how much presentation was getting offloaded to CSS3 and how CSS3 really needs to be thought of along with HTML5. Everyone's covering different aspects, copping a different feel of the elephant, like the parable of the blind men.
Oh, and not just 1AM... 1AM on a Friday night / Saturday morning! But it was so frickin satisfying getting my graph generation into SVG. These are the most exciting times to code since the mid 90s.
We all like to enjoy our lives, and sometimes it seems as if working is the opposite of that. But it's hard to do better than loving your work too. Then you're loving your life when you're working AND when you're not working.
I'll cruise so successfully in tight slacks at the fox bar next weekend.
@Steve,
HTML5 is cool; I really want to embrace more CSS3 stuff. I think as long as we don't worry about decent degredation (ie. not worrying about rounded corners, drop shadows), then using CSS3 should make the code much easier to write.
Looking forward to our future conversations.
@Ben,
Yes, you are right, please let us know how you go with CF portable!
@Ben,
What features you can use and when:
http://www.caniuse.com/
(Clearly GoogleChrome-sponsored, but the info is good, and they seem entitled to toot their own horn when you see it all laid out like that.)
@Steve,
Sweet website! Thanks.
@Ben,
Returning to the topic of this article, in cache_manifest.cfm, you use a manually-maintained version number to indicate that something pointed to by the cache manifest has changed, even though the cache manifest itself has not changed.
Since cache_manifest.cfm is a CFM file, let me propose an alternative: a directory watcher and a Server-scope variable to make version maintenance automatic, like so:
The directory watcher looks for file changes in the directory. If a file has changed, you read it and calculate the MD5 in hex (CF's Hash function). You store this into Server.MyStruct using the file name as the struct key. Suppose that it's index.html, for example:
(cfset Server.MyStruct["index.html"] = Hash(CFFile.FileContents))
Then you create a summary value over all of the file names in the whole directory:
(cfset MyString = "")
(cfloop index="MyKey" list="#StructKeyList(Server.MyStruct)")
(cfset MyString &= Server.MyStruct[MyKey])
(/cfloop)
(cfset Server.MySummary = Hash(MyString))
Then, in cache_manifest.cfm, you say
(cfoutput)
## Cache Manifest Version: #Server.MySummary#
(/cfoutput)
The only time you EVER go through the overhead of reading a file and recalculating MySummary is if one of the files changed. You don't reread the other files that didn't change, because they're not on the directory watcher's to-do list. 99% of the time, files aren't changing, so Server.MySummary doesn't change. Also, Server.MySummary is retrieved at memory speeds, not I/O speeds. So it's low overhead.
It's like automatically resetting the Cache Manifest Version number with no effort. And you never forget to do it.
Of course, you'd have to recalc the values over all of the files in your OnServerStart, because the Server scope disappears when you reboot.
Just an idea inspired by your excellent design choice to make cache_manifest.cfm dynamic.
Oops, missing pound sign:
list="#StructKeyList(Server.MyStruct)#"
I really should proofread better.
@Steve,
Definitely an interesting idea. If you really wanted to make it extra cool, you could have the directory watcher read the cache manifest and only monitor the files that are meant to be cached in the manifest (ignoring things in the API and whatnot).
I've never actually worked with Gateways in ColdFusion; but, very thought provoking.
@Steve,
I *finally* got around to playing with the cache events:
www.bennadel.com/blog/2029-Using-HTML5-Offline-Application-Cache-Events-In-Javascript.htm
Cool stuff. I wonder what these are best used for.
Ben,
I have been playing around with cache manifest for a few days, and made good progress thanks in no small part to your helpful posts.
I have a question which I am not finding answers to on the web. Hopefully, you are someone else can help...
I have a web application in which most pages will be cached using cache manifest. The application allows access to a number of audio and video files (which can be large - several megabytes per file).
It seems to me I don't want to include all the media files in the cache manifest because that would mean 100's of megabytes being downloaded and cached.
What I would really like is for the browser to cache the media files when they are accessed by the user. So that any file that has been accessed becomes automatically available offline.
Is there a way to achieve this using cache manifest ?
Hi Ben,
thx for your great article. I did html and javascript for iphone web apps offline. But it's not ok in my iphone, but ti's working offline in firefox browser. I don't know what really happned.
can you pls help me something?
Really good blog thanks
We are an outsourcing data entry company in India offering data entry, data processing, data conversion, online data entry, and data capture services with the help of professional data entry operators
Hi.
Thanks for the informative blog. I apologize in advance for naivete on html coding, but could you answer a really easy question? Since I have not yet coded an html5 website to test this, I am unable to find out on my own.
How to calculate what the file size would be for the manifest file - assuming a perfectly-designed website - that stores simple text data in the most basic format with the ultimate goal of exporting to a tab-delimited text file?
Example:
A website that creates 10 columns of data (10 characters per column) every second. After 100 seconds of running, the website has created a set of data with 1,000 data points, each with 10 characters, for a cumulative total of 1,000,000 characters, plus whatever manifest file formatting, tab delimiting instructions, etc. is required.
What would be the filesize for this 1 million character data set? Suppose it ran for 1,000 seconds and created 10 million characters of data. What would be the estimated manifest file size?
Thanks in advance for your perspective!
The concept of cache storage is beyond interesting, but I have some issues with it's implementation. Here are a few things I'm finding annoying as I play around with it.
(1) If a change has been made, it re-caches ALL the files not just the ones which have changed.
(2) I'd like to use this to cache a few images, but it caches the page I call the manifest from even if I have it listed in the Network area for not caching.
(3) It appears that the user must remain on the same page until all files are downloaded as if they go to another page it stops downloading, and even if they go to another page which calls the manifest it restarts downloading from the beginning. Even if returning to the same page it'll restart.
(4) I'm also not real keen on it pulling from storage and requiring a reload if the page has changed. I'd prefer having an option as I'd probably select to have it load from the server instead of cache storage so that the user is getting the most up-to-date page.
With these limitations I can't see this as all that useful as I once thought it'd be. Am I missing something?
Hi ..
It is an excellent example to understand application cache..But i would like to request you..
could you shared all the project of " Experimenting With HTML5's Cache Manifest For Offline Web Applications".So that i can run from my local..
giv project including images..
Great Article. Excellent overview and tutorial!
Hi Ben,
I have just read your "Experimenting With HTML5's Cache Manifest For Offline Web Applications" and found this totally fasinating. Having played around with the example scripts that you have provided I tried but failed to come up with a solution to my issue.
What I am trying to do is write a web page and when the connection to the internet is lost display an another page or the same page while the browser is waiting for the internet connection to become available again.
Is this the sort of think "Cache Manifest" could do.
Any help or pointers would be greate.
Many thanks in advance, ind regards,
Dereck
While implementing HTML 5 caching for a major web application we found several very interesting nuances of HTML 5 caching ( http://gadgetophilia.com/advanced-tips-with-html-5-caching/ ) based on our experience. Check the link for details.