HTML 5 Cache manifest gets cached itself
I have a problem of that it seems that the cache.manifest file gets cached itself. Meaning every changes to the file are not being noted by (Mobile) Safari, so it will never update and always show the last cached files.
I tried to avoid it using an .htaccess
file in the same directory as the cache.manifest
file:
ExpiresActive On
ExpiresDefault "access"
That didn't help so I changed cache.manifest in a php file that contains the following headers:
header("Expires: Mon, 26 Jul 1990 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cach开发者_运维百科e-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header('Content-Type: text/cache-manifest');
Anyone have other ideas of how I can make sure the cache file itself will get retrieved if possible?
Works on: Safari (Desktop), Chrome (Samsung Galaxy Tab v10.1), Firefox
Fails on: Chrome, Safari (iOS)Renamed the cache.manifest.php back to cache.manifest and added the following lines to the .htaccess
<IfModule mod_expires.c>
Header set Cache-Control "public"
ExpiresActive on
# cache.manifest needs re-requests in FF 3.6 (thx Remy ~Introducing HTML5)
ExpiresByType text/cache-manifest "access plus 0 seconds"
</IfModule>
If I change the revision comment within the cache.manifest and refresh it on Safari (iOS) it still shows me the old file. I am clueless.
According to the HTML5 documentation, if an application cache manifest file is byte-for-byte the same as a previous one, regardless of HTTP cache headers for expiry/etc, it is considered to not require an update.
At the bottom of your cache manifest file, you need to include a comment at the bottom of the file with the timestamp of the most recently modified file, e.g.:
# last modified: Thu, 30 Jun 2011 01:19:46 GMT
This will break up the byte-for-byte identicalness, even if the list of files remains the same but a few are updated.
As alluded to in other answers, cache manifests are a real pain to deal with.
I've tweaked a PHP manifest "build" script for my HTML5 notepad app.
Tested and working on Chrome, Firefox, IE8+, Android and iOS.
It's open source and available here: https://github.com/JasonHanley/note5/blob/master/build.php
I also use the ExpiresByType text/cache-manifest "access plus 0 seconds" in my .htaccess and I believe that is necessary in addition to generated manifest timestamps.
I've just stumbled onto this one myself, and in a similar vein to SimpleCoders suggestion I'd suggest that if you are using Apache you can generate the cache.manifest using Server Side Includes, eg:
CACHE MANIFEST
# <!--#flastmod file="index.html"-->
# <!--#flastmod file="whatever.js"-->
# <!--#flastmod file="whatever.css"-->
whatever.js
whatever.css
That way, whenever any of those files are updated, the manifest will change automatically. You may also need to enable includes for that file and disable caching, eg: Apache config something like:
Alias /whatever /var/www/whatever
<Directory /var/www/whatever>
Options +Includes
AddHandler server-parsed .manifest
</Directory>
CacheDisable /whatever/ihealth.manifest
Check your server logs to make sure you're returning the file with a "200 Okay" rather than a "304 Not Modified".
The cache manifest is a terrible piece of technology.
The browser is not caching the manifest; instead, it's just failing to recognize that it has changed which is what you are observing. Try adding a random comment or two to your manifest (prepend comments with #
) and then see if it works.
Just modifying files that the manifest references won't trigger the browser to redownload the manifest. If this is what you were hoping for, then try this: Use a PHP file to generate your manifest. Of course, use header
to set the proper MIME type. After you have echoed out all of your resources, echo out the hash of the timestamp of all of those resources. That way, if one of them is modified, the manifest file changes. This is what I'm using:
// Collect a list of resources we need to check (customize to your needs)
$files = array(
"/scripts/script1.js",
"/scripts/script2.js",
"/scripts/script3.js",
"/scripts/script4.js",
"/css/style.css"
);
$filetime = 0;
foreach ($files as $file) {
$filetime += filemtime($file);
}
// This echoes out the hash of the filetimes as a comment
echo "#" . sha1($filetime);
精彩评论