I’ve also just built an offline app, and found it became much easier to work with appcache when I switched my mental model to that of a native app.
The manifest is just the description of the app bundle that you upload. When you upload a new version, you have to put a new version in the app bundle, just like native apps. You have to explicitly market everything that the bundle contains, just like native apps. Upgrading the app is done out of band, and the app always loads from the offline copy, just like native apps.
The problems described with bad connectivity occur on native apps as well. The smoothest native apps solve this by doing all online communication out-of-band (so the user can keep interacting), and by letting the user trigger when to download content (only the user can know when their network connectivity is good enough).
Maybe I just had a long day, but I found the comedy intro a bit off putting. It’s a long article already. I don’t mind the title, although classy it isn’t.
Copy & paste the code below to embed this comment.
superted
So I was a little bit amazed that anyone could be offended by the word douchebag.
I thought maybe there were some cultural differences at play here and that on the other side of the pond (jake is british) the D word is more akin to the C word. See, over here douchebag is almost comedic in it’s lack of offensiveness, it’s the kind of word you might hear in elementary school before kids learn to cuss properly.
So I thought I’d do some research and it didn’t take me long to find this article:
http://www.nytimes.com/2009/11/14/business/media/14vulgar.html
It states in the article that the word douche ‘has surfaced at least 76 times already this year on 26 prime-time network series’.
Now you may not think this is right but what it does tell you is that the word you have taken offence to is now broadly deemed inoffensive enough to broadcast during primetime.
I’d say if a word is inoffensive enough for prime time it’s definitely inoffensive enough for a tech blog post dealing with advanced javascript topics.
On a final note I’d like to say that you taking offense to an an inoffensive word has nothing to do with Jake’s professionalism.
Agreed, things get a lot easier when you act like you’re building an app, that’s why making Spritecow work offline was relatively simple compared to Lanyrd.
Unfortunately, building sites in that way makes usual best practices such as progressive enhancement pretty tough.
Copy & paste the code below to embed this comment.
BrainSurgeon
I’m surprised people couldn’t get over the title enough to appreciate the content. This was some of the most comprehensive AppCache guidance I’ve seen yet.
Thanks for compiling it and making me laugh at the same time. To the other d-bags on here, enjoy your myopic lives.
Copy & paste the code below to embed this comment.
JoeSnellPDX
I totally dug your article. The information is on point, easy to follow and has already answered some of my questions regarding this topic. That being said, the wit, humor and creativity you employed was quite enjoyable. I’ll be looking forward to reading another article from you in the future.
Copy & paste the code below to embed this comment.
davidzuch
Thank you for the really informative article, it really helped me understand a lot of the problems I encountered with the Application Cache. However, you kind of lost me here:
// Get the page content
var pageHtml = document.body[removed];
var urlPath = location.pathName;
// Save it in local storage
localStorage.setItem( urlPath, pageHtml );
// Get our index
var index = JSON.parse( localStorage.getItem( index’ ) );
// Set the title and save it
index[ urlPath ] = document.title;
localStorage.setItem( ‘index’, JSON.stringify( index ) );
I tried running that in the console, but this line here returns null (after adding the missing quote, of course):
var index = JSON.parse( localStorage.getItem( index’ ) );
I have to assume you left out a step? Otherwise the code beyond that point just doesn’t do anything (besides returning errors).
That particular code example fails if ‘index’ isn’t an object, which would be done as part of an init script. It’s not far from pseudo-code. See the full code at https://github.com/jakearchibald/appcache-demo/blob/master/www/localstorage-cache/js/offliner-v1.js#L62 for an end-to-end example.
Copy & paste the code below to embed this comment.
xmlblog
My generation has a penchant for foul language. On our watch bitch and son-of-a-bitch have made it past the censors on the public airwaves. So you understand where I’m coming from, I’m no puritan—I use “colorful” language myself (perhaps too often I’m ashamed to say). But there are still places where I don’t. I don’t use expletives in meetings, or when toasting at weddings, in churches or temples, at the dinner table, and a few other places where the clearly seem inappropriate. On the other hand, great writers do often include distasteful words to make a sharp point. But they do so judiciously. If I understand you correctly, you made a conscious decision to employ the term, “douchebag.” Fine, but I think it was unwarranted and counterproductive in this case.
Copy & paste the code below to embed this comment.
Kris Meister
Nice to see a technical article with sass.
I finished a project recently which created a mobile Web-App for distribution on iOS and Android. Web-Apps are an especially convenient use of AppCache. The user bookmarks the app to their homescreen and upon opening the app runs in full-screen outside the browser and with AppCache will run without web connectivity.
In my case I was only building a prototype and didn’t run into many of the update issue you faced. But the client was very relieved that they didn’t need to integrate the whole iOS provisioning profile system.
I agree with your article that bookmarking individual content articles needs a solution and your technique of using LocalStorage fits the bill.
However, I think the future of AppCache is in creating Mobile Web-Apps that circumvent the proprietary vendor marketplaces.
Well done, sir, both for the technical content and writing style. Having hit most of those gotchas during the last year, I can only wish this had existed earlier.
@Seannachie: “Blatantly derogatory” to whom, exactly? Our nation’s poor, oppressed douchebag minority? The manufacturers of vaginal nozzle syringes? Or perhaps you’re afraid he’s hurting ApplicationCache’s feelings? But go ahead, please suggest an equally snappy, fetching and accurate alternative title then.
Thank you for the article. I am similar in my approach to development in terms of attitude. We don’t have to take ourselves too seriously and I find the ones that do have much less to contribute.
That is a great article, thank you very much. I learned a lot from it. Gotcha #6 could easily be avoided by providing different .manifest files for different platforms though.
Thanks very much for your greatful job. But I find that the “iframe hack” is not work in chrome(26), Each time I refresh the page(http://appcache-demo.s3-website-us-east-1.amazonaws.com/localstorage-cache/), static resources in fallback.html load from cache, but the same resources in index.html still download from server.
Copy & paste the code below to embed this comment.
Jempey
First of all, a great article and a great introduction into the story of going offline. The application cache is indeed not that easy to implement and there are a lot of pitfalls. But when it works, it works, and it works perfectly! To say… for the lastest popular desktop and mobile browsers.
In an attempt for a newspaper project I had to develop an android html5/javascript application which needed to work offline. Not a big problem at all, but when migrating everything to an android webview, allmost everything went wrong. Making the application cache work in an android webview seems to be extremely difficult. We haven’t found a solution yet, but for instance, the demo page of A List a part doesn’t work either.
More on this issue @ https://github.com/kurti-vdb/AppcacheDemo
Caching in general is not easy to get right, and caches on top of caches are always going to be a barrel of fun to debug, especially when they’re incredibly sensitive to all kinds of implicit assumptions and state.
For most purposes, AppCache does nothing more than the Expires HTTP header has done for years.
Content sent with future-dated Expires even works offline. (Until the user hits refresh, anyway—which is really a sign of what browser vendors have had to do to accommodate bad caching implementations. I’m interested to see if they will hold out any better against bad AppCache implementations.)
But AppCache is also a pre-loader, which is an entirely separate thing from caching, and I’m not sure they should be conflated. For a given resource you might reasonably want to cache but not pre-load, and for another pre-load but not cache.
For any non-trivial application, which is to say any application for which caching and preloading might be useful, the work of cache invalidation and decisions about what to pre-load, end up being done in application code. Letting the browser make some of the decisions independently of the app code leads to coupling, which leads to complexity, which leads to bugs.
33 Reader Comments
Back to the Articlejsebrech
I’ve also just built an offline app, and found it became much easier to work with appcache when I switched my mental model to that of a native app.
The manifest is just the description of the app bundle that you upload. When you upload a new version, you have to put a new version in the app bundle, just like native apps. You have to explicitly market everything that the bundle contains, just like native apps. Upgrading the app is done out of band, and the app always loads from the offline copy, just like native apps.
Reasoning from there it’s obvious to me that (A) the app should be a single page js app, (B) FALLBACK is a legacy mechanism not to be used for new apps, and © all dynamic content belongs in localstorage.
The problems described with bad connectivity occur on native apps as well. The smoothest native apps solve this by doing all online communication out-of-band (so the user can keep interacting), and by letting the user trigger when to download content (only the user can know when their network connectivity is good enough).
fritz from london
Maybe I just had a long day, but I found the comedy intro a bit off putting. It’s a long article already. I don’t mind the title, although classy it isn’t.
Anyway, thanks for sharing the info.
superted
So I was a little bit amazed that anyone could be offended by the word douchebag.
I thought maybe there were some cultural differences at play here and that on the other side of the pond (jake is british) the D word is more akin to the C word. See, over here douchebag is almost comedic in it’s lack of offensiveness, it’s the kind of word you might hear in elementary school before kids learn to cuss properly.
So I thought I’d do some research and it didn’t take me long to find this article:
http://www.nytimes.com/2009/11/14/business/media/14vulgar.html
It states in the article that the word douche ‘has surfaced at least 76 times already this year on 26 prime-time network series’.
Now you may not think this is right but what it does tell you is that the word you have taken offence to is now broadly deemed inoffensive enough to broadcast during primetime.
I’d say if a word is inoffensive enough for prime time it’s definitely inoffensive enough for a tech blog post dealing with advanced javascript topics.
On a final note I’d like to say that you taking offense to an an inoffensive word has nothing to do with Jake’s professionalism.
einarlove
Truly loved the wit and humor. It made the read enjoyable and was greatly appreciated!
mnot
Nice writeup. AppCache does indeed oversell itself.
Personally, I think we need something better. FWIW I’ve written more here:
* “Fixing AppCache”:http://www.mnot.net/blog/2011/06/19/offline_web * “Better Browser Caching”:http://www.mnot.net/blog/2011/08/28/better_browser_cachingbut really, they only scratch the surface.
Jake Archibald
Agreed, things get a lot easier when you act like you’re building an app, that’s why making Spritecow work offline was relatively simple compared to Lanyrd.
Unfortunately, building sites in that way makes usual best practices such as progressive enhancement pretty tough.
BrainSurgeon
I’m surprised people couldn’t get over the title enough to appreciate the content. This was some of the most comprehensive AppCache guidance I’ve seen yet.
Thanks for compiling it and making me laugh at the same time. To the other d-bags on here, enjoy your myopic lives.
BrainSurgeon
http://www.quora.com/English-language/When-did-the-term-douchebag-enter-the-popular-parlanc
JoeSnellPDX
I totally dug your article. The information is on point, easy to follow and has already answered some of my questions regarding this topic. That being said, the wit, humor and creativity you employed was quite enjoyable. I’ll be looking forward to reading another article from you in the future.
Thanks!
davidzuch
Thank you for the really informative article, it really helped me understand a lot of the problems I encountered with the Application Cache. However, you kind of lost me here:
I tried running that in the console, but this line here returns null (after adding the missing quote, of course):
I have to assume you left out a step? Otherwise the code beyond that point just doesn’t do anything (besides returning errors).
Jake Archibald
That particular code example fails if ‘index’ isn’t an object, which would be done as part of an init script. It’s not far from pseudo-code. See the full code at https://github.com/jakearchibald/appcache-demo/blob/master/www/localstorage-cache/js/offliner-v1.js#L62 for an end-to-end example.
xmlblog
My generation has a penchant for foul language. On our watch bitch and son-of-a-bitch have made it past the censors on the public airwaves. So you understand where I’m coming from, I’m no puritan—I use “colorful” language myself (perhaps too often I’m ashamed to say). But there are still places where I don’t. I don’t use expletives in meetings, or when toasting at weddings, in churches or temples, at the dinner table, and a few other places where the clearly seem inappropriate. On the other hand, great writers do often include distasteful words to make a sharp point. But they do so judiciously. If I understand you correctly, you made a conscious decision to employ the term, “douchebag.” Fine, but I think it was unwarranted and counterproductive in this case.
Kris Meister
Nice to see a technical article with sass.
I finished a project recently which created a mobile Web-App for distribution on iOS and Android. Web-Apps are an especially convenient use of AppCache. The user bookmarks the app to their homescreen and upon opening the app runs in full-screen outside the browser and with AppCache will run without web connectivity.
In my case I was only building a prototype and didn’t run into many of the update issue you faced. But the client was very relieved that they didn’t need to integrate the whole iOS provisioning profile system.
I agree with your article that bookmarking individual content articles needs a solution and your technique of using LocalStorage fits the bill.
However, I think the future of AppCache is in creating Mobile Web-Apps that circumvent the proprietary vendor marketplaces.
jpatokal
Well done, sir, both for the technical content and writing style. Having hit most of those gotchas during the last year, I can only wish this had existed earlier.
@Seannachie: “Blatantly derogatory” to whom, exactly? Our nation’s poor, oppressed douchebag minority? The manufacturers of vaginal nozzle syringes? Or perhaps you’re afraid he’s hurting ApplicationCache’s feelings? But go ahead, please suggest an equally snappy, fetching and accurate alternative title then.
duppyconquer
I had to create this account to say…
@SEANNACHIE is a Douchebag! LMAO.
Ganesh
Its a great article :)
バイオの買物.com 代表 加々美直史
Great article. Doing something similar myself, the use of FALLBACK was especially informative.
Eric Brown 1
Good article. I’m just laughing at some of the cry baby comments. @SEANNACHIE… what an AppCache!!
Jason Sebring
Thank you for the article. I am similar in my approach to development in terms of attitude. We don’t have to take ourselves too seriously and I find the ones that do have much less to contribute.
Zero Point Surfer
That is a great article, thank you very much. I learned a lot from it. Gotcha #6 could easily be avoided by providing different .manifest files for different platforms though.
blessdyb
Thanks very much for your greatful job. But I find that the “iframe hack” is not work in chrome(26), Each time I refresh the page(http://appcache-demo.s3-website-us-east-1.amazonaws.com/localstorage-cache/), static resources in fallback.html load from cache, but the same resources in index.html still download from server.
Jempey
First of all, a great article and a great introduction into the story of going offline. The application cache is indeed not that easy to implement and there are a lot of pitfalls. But when it works, it works, and it works perfectly! To say… for the lastest popular desktop and mobile browsers.
In an attempt for a newspaper project I had to develop an android html5/javascript application which needed to work offline. Not a big problem at all, but when migrating everything to an android webview, allmost everything went wrong. Making the application cache work in an android webview seems to be extremely difficult. We haven’t found a solution yet, but for instance, the demo page of A List a part doesn’t work either.
More on this issue @ https://github.com/kurti-vdb/AppcacheDemo
Tom Love
Caching in general is not easy to get right, and caches on top of caches are always going to be a barrel of fun to debug, especially when they’re incredibly sensitive to all kinds of implicit assumptions and state.
For most purposes, AppCache does nothing more than the Expires HTTP header has done for years.
Content sent with future-dated Expires even works offline. (Until the user hits refresh, anyway—which is really a sign of what browser vendors have had to do to accommodate bad caching implementations. I’m interested to see if they will hold out any better against bad AppCache implementations.)
But AppCache is also a pre-loader, which is an entirely separate thing from caching, and I’m not sure they should be conflated. For a given resource you might reasonably want to cache but not pre-load, and for another pre-load but not cache.
For any non-trivial application, which is to say any application for which caching and preloading might be useful, the work of cache invalidation and decisions about what to pre-load, end up being done in application code. Letting the browser make some of the decisions independently of the app code leads to coupling, which leads to complexity, which leads to bugs.