Using the HTML5 cache manifest with dynamic files
Published on 25/01/2010I recently added HTML5 cache manifest support to Showtime in an attempt to decrease load times for users on older hardware and for those with spotty network connectivity. As Stoyan Stefanov mentions: the current iPhone will not cache individual components if they are larger than 15K and will wipe all caches when the device is powered down or restarted.
This represents an inherent issue with using the jQTouch library for iPhone-related web app development. Although jQTouch keeps itself fairly focused in terms of support (and thus lean), jQuery is bloated by its necessity to support all manner of rendering platforms and browser technologies. At the time of writing, a minified version of jQuery 1.4 will weigh in at about 72KB. As a result, jQuery must be remotely served each time your web application is accessed. While there has been talk of forking the jQuery codebase to shave away all non-essential (specifically, non-Webkit related implemenations and other pieces of fluff), those of us currently running web apps need a slightly more immediate solution.
That solution is the HTML5 cache manifest. As the Safari Dev Center explains:
The manifest file specifies the resources—such as HTML, JavaScript, CSS, and image files —to download and store in the application cache. After the first time a webpage is loaded, the resources specified in the manifest file are obtained from the application cache, not the web server.
Although I had read about the cache manifest around the Internet, it wasn’t until I read Jonathon Stark’s wonderful Building iPhone Apps with HTML, CSS, and JavaScript: Making App Store Apps Without Objective-C or Cocoa that I came across a cleverly dynamic means of generating a manifest and supplying it to the browser. There was only one problem: Stark’s implementation didn’t account for web apps that made use of dynamic content.
To resolve the issue, I forked his manifest.php implementation to account for .php files:
header('Content-Type: text/cache-manifest'); echo "CACHE MANIFEST\n"; $hashes = ""; $lastFileWasDynamic = FALSE; $dir = new RecursiveDirectoryIterator("."); foreach(new RecursiveIteratorIterator($dir) as $file) { if ($file->IsFile() && $file != "./manifest.php" && substr($file->getFilename(), 0, 1) != ".") { if(preg_match('/.php$/', $file)) { if(!$lastFileWasDynamic) { echo "\n\nNETWORK:\n"; } $lastFileWasDynamic = TRUE; } else { if($lastFileWasDynamic) { echo "\n\nCACHE:\n"; $lastFileWasDynamic = FALSE; } } echo $file . "\n"; $hashes .= md5_file($file); } } echo "# Hash: " . md5($hashes) . "\n";
The above code should be fairly clear. Jonathon Stark’s original manifest.php made use of PHP5′s RecursiveDirectoryIterator class to generate a complete list of all the resources your web application relies upon (with the exception of the manifest.php file itself). I’ve simply altered it slightly to do a fairly primitive regex check to catch any files with a .php extension and preface those files within the manifest with a NETWORK flag (which forces the files to be requested from the web server, rather than the local cache).
Documentation on the application cache is fairly scarce at the moment, and I’m not professing to being any kind of expert. I just hope this code can help anyone else looking to use the cache manifest as a means of speeding up their dynamic mobile web applications.