
Application Cache Is A Douchebag - mathias
http://www.alistapart.com/articles/application-cache-is-a-douchebag/
======
simonw
Jake based this article on the work he did on our offline HTML5 mobile app (
<http://m.lanyrd.com/> ) - doing offline right is surprisingly trick and full
of edge cases, and I haven't seen them documented in as much detail anywhere
else.

~~~
Joeri
<http://appcachefacts.info/> contains most of the gotcha's.

------
pavel_lishin
> GOTCHA #8: REDIRECTS TO OTHER DOMAINS ARE TREATED AS FAILURES

So are redirects to your own domain, though not quite the same as here. What
it means that while downloading the resources specified in your manifest file,
encountering a 302 means that the entire applicationCache fails. Downloaded 99
static files fine, and then get a 302? Congratulations, your cache is now
invalid.

> GOTCHA #9: AN EXTRA HOOP TO JUMP THROUGH FOR XHR > You can make XHR requests
> to cached resources while offline, unfortunately older versions of WebKit
> finish the request with a statusCode of 0, which popular libraries interpret
> as a failure.

Not that much older. This is the case for iOS5.1, the last time I checked, and
for every Android phone I've tested this on as well.

~~~
jaffathecake
Yeah, redirects to manifest entries makes the cache fail, but a 302 on a page
the user visits (which is covered by a FALLBACK rule) is fine as long as it's
to the same domain.

As for GOTCHA #9, I thought that was fixed in iOS4. But yeah also fails on
Blackberry playbook and Andorid 3 & 4\. Actually works on Android 2.3 (unless
I'm mistaken), which isn't suprising as there are loads of regressions in the
Android 3 browser.

~~~
pavel_lishin
We do mobile web development, and we like to scale down images to the
appropriate size for any given phone. I was hoping to be clever, and instead
of redirecting every user to a hardcoded image path
(/illustration.17.503x302.jpg), to just redirect them to /illustration/17 -
which would generate the properly sized image, and use a redirect to display
it.

Spent a few days on it. Worked great online. Then I discovered that putting
/illustration/17 in the cache manifest made the entire thing fail, since it's
a redirect.

C'est la days of wasted work.

~~~
jaffathecake
Bah. Nice idea though. So far we're using a double-sized sprite image whether
you're on a high dpi device or not. Thankfully everything that supports
appcache supports background-size, and the 'waste' of serving high-res sprites
to phones that couldn't use them was negligible (it's basically just
[http://static.lanyrd.net/css/mobile-
web/img/sprites5@2x.53a3...](http://static.lanyrd.net/css/mobile-
web/img/sprites5@2x.53a3a8cb.png)).

~~~
pavel_lishin
Most of the images we serve are loaded from a different server, and can be
dynamically changed by editors, etc. Putting them into a sprite would probably
be more work than it's worth.

------
Joeri
Appcache is an app packaging mechanism, and should be treated as such. The
manifest is the equivalent of a plist or xml file describing the app package.
It actually makes a lot of sense when you view it like that. By extension, you
should only put stuff into appcache that you would put in a native app bundle.

I've built an appcache app that is a bunch of static javascript (in the CACHED
section) contacting a bunch of services in the NETWORK section. There is no
FALLBACK section, because any resource is either online or offline, but never
both. The UI is designed so the user knows which content is online, and can
decide for themselves if they have good enough connectivity. Dynamic content
goes into localstorage if it needs to be persisted. This way of using appcache
works very well and is mostly painless.

------
peterwwillis
_Yes, that’s right, I verbified “offline.” Yes, I verbified “verb.” Feel free
to inbox me grammar complaints that I’ll trashinate._

I think more worders should matriculate into the Strongbad School of
Verbinizin' Speechy Things.

~~~
ericclemmons
I was going to comment on the same line! It's very easy for articles like this
to come across dry, but writing that lets the author's wit shine through helps
pacing significantly, almost like comic relief after a tense moment.

------
saurik
> GOTCHA #3: THE APPLICATIONCACHE IS AN ADDITIONAL CACHE, NOT AT ALTERNATIVE
> ONE

This section is not quite true, at least for WebKit. This article states that
the application cache will use the normal browser cache when making outgoing
requests, honoring whatever cache control headers were sent by the server.
What actually happens is that the browser always forces a revalidation of the
content with the server, regardless of what the cache control headers that had
been served.

Now, I certainly /wish/ it were the case that it honored the normal browser
cache, but it simply doesn't. The result is that the application cache makes
these outgoing requests painfully and arduously one-at-a-time, waiting for the
previous one to entirely complete before making the next one... over a mobile
data connection this takes /forever/, and it is quite possible that it simply
does not finish by the time the process is aborted by one of these needless
server requests failing or the window being closed.

Normally, you can mitigate these issues by sending files with "cache this
effectively forever" headers and always using unique filenames, but with the
application cache manifest system (which you are going to be using to support
guaranteed-consisten offline operation) you are forced to wait for every
request to resubmit before seeing the update.

Here is the code from WebKit's ApplicationCacheGroup.cpp, where you can see
"max-age=0" being sent as Cache-Control for the outgoing requests. (Sending
that header as a user-agent serves to "force any intermediate caches to
validate their copies directly with the origin server", per RFC2616).

    
    
        PassRefPtr<ResourceHandle> ApplicationCacheGroup::createResourceHandle(const KURL& url, ApplicationCacheResource* newestCachedResource)
        {
            ResourceRequest request(url);
            m_frame->loader()->applyUserAgent(request);
            request.setHTTPHeaderField("Cache-Control", "max-age=0");

~~~
jaffathecake
I don't think this is the case, not in Chrome anyway.

See <http://www.youtube.com/watch?v=q7QL0NAwES8> \- All files are "must-
revalidate" except the JS file which is far-future cached. When the manifest
is changed an update is triggered, all files are updated except the JS file,
which is assumed to be fresh because of the far future expiry.

You see similar behaviour when no caching headers are served, heuristics take
over & files may be updated from the normal browser cache rather than going to
the server.

~~~
saurik
I will then be much more specific and say "MobileSafari". My mobile
application is part of an iOS application, so I only use and care about
MobileSafari as a target. I definitely am quite careful with my Cache-Control
headers, and am documenting this not just with logs but with WebKit code.

(edit/clarification: While I get this code from the WebKit repository, I
forgot that the specific area of WebKit I'm looking at is WebCore, so I should
really be calling it WebCore and not WebKit, considering they are separate
libraries and quite separate projects on some platforms.)

Someone else I know (who may or may not decide to actually chime in) saw this
interaction and decided to do some tests with various browsers, stating that
1) Safari worked as I said, 2) Firefox refetched the request but did not set
the Cache-Control header, and 3) Chrome worked as you say.

~~~
jaffathecake
Confirmed! Interesting. Safari on OSX and iOS makes the request regardless.
Firefox didn't request the far-future file, but also didn't request one of the
must-revalidate files. Not sure what it's doing. Good spot.

------
Throlkim
Interesting read and nicely written. It's just a shame HN doesn't have a
'report' feature like Reddit, as I can't report all the whiners in this thread
as douchebags.

------
logjam
Male here.

Most professionals will no longer bother to read an article with a headline
that uses insulting, sexist words.

If you worked for me and wrote that title for an article about something we
were working on, you wouldn't work for me any more. Period.

Tech culture is moving away from childishness, and there were a large number
of other words you could have used in your title.

Go learn some.

~~~
ajross
"Douchebag" is gendered, I guess. It's not clear to me that it's sexist. In
common usage, it virtually always refers to a man. The actual relation to a
"douche" is mostly vestigial.

I think you have to let this one go. Fighting against linguistic churn as a
proxy for "sexism" seems to me like it hurts more than it helps, as it feeds
the "PC feminazi" meme. There are better fights to pick than this one.

~~~
Rudism
There was an interesting (and timely) question on Quora about when the word
douchebag entered common parlance, with some good answers given:

[http://www.quora.com/English-language/When-did-the-term-
douc...](http://www.quora.com/English-language/When-did-the-term-douchebag-
enter-the-popular-parlance)

Seems like its use as a nickname/insult really exploded in the 70's and 80's.
I'd tend to agree that tying the word to sexism is a bit of a stretch--it's
probably just being used because it sounds like a naughty word, and anything
more explicit or profane wouldn't get past the censors.

------
parfe
Sweet, let's unabashedly support more sexism! That's what the tech industry
needs.

Somehow, an article describing caching of web applications manages to
denigrate women, _for no reason_.

The underrepresentation of women in tech is caused by this mindless sexism,
like body-shaming women. Douche bag is a sexist insult. You're insulting your
target by associating them with feminine care products. It's a direct
associating between "This thing is womanly so it is bad." Even after several
other stories these digs at women still get publicized!

~~~
ajpiano
Even in feminist circles, the the idea that "douchebag" is definitely sexist
and denigrating is far from a settled argument:
[http://www.feministe.us/blog/archives/2009/11/16/in-
defense-...](http://www.feministe.us/blog/archives/2009/11/16/in-defense-of-
douchebag/) <http://mooretoons.com/2008/08/20/is-douchebag-sexist/>

At the core of this argument is the idea that the "popularization" of act of
douching itself was itself anti-woman, insofar as it categorised normal
women's bodies and actions as unclean and shameful, and in turn advocated an
unhealthy "solution" to a problem largely invented by the patriarchy.

Nevertheless, I cringed ever-so-slightly when Jake gave this talk at JSConf
and again when I saw it here on HN, because I knew that in recent months,
among all the other _salient_ gender issues that have been floating about, a
bunch of people also "heard douchebag was sexist," and so would lodge this
reservation.

~~~
parfe
He's certainly not making the point that douches were invented to shame women.
He's using the negative association of what douches are for. You seem to be
making a "taking it back" argument when he clearly did not intend that
meaning.

Not using douchebag is easy! Step 1) Just Don't! Now you won't have to deal
with causing strife with women in tech.

~~~
cube13
>He's using the negative association of what douches are for. You seem to be
making a "taking it back" argument when he clearly did not intend that
meaning.

Modern medicine considers douches to be dangerous to use. Not sure how making
a negative of something that is, in fact, negative is a bad thing.

