iOS Web App - how to deal with overzealous app caching?
Asked Answered
S

1

15

I've been developing a pretty complicated HTML5 web app for the past month. Last night my iPhone suddenly decided to cache all JS, CSS, and images and not load any updated copies. This happened on my partner's iPhone too, so I'm going to assume it's affecting all users of our app.

Needless to say, clearing the browser cache, deleting the web app, restarting the phone, & restarting the wireless connection do nothing to fix the problem.

Removing <meta name="apple-mobile-web-app-capable" content="yes"> solves the problem, but creates a new problem since we need the app to run like...an app.

We're not going to go around appending the old trick ?number to the end of all our scripts, stylesheets, and images either. That's ridiculous. Also -- if we were to implement something like this, it would have to be some sort of dynamic JS implementation. Our app is one HTML page that loads most scripts, and additional pages are AJAXed in, additional data is also obtained via AJAX. I guess this could be done, but I'm hoping for a more elegant solution. Ya know, I feel like I shouldn't have to do anything since this all worked without a hitch for an entire month.

Using the cache-control, expires, and pragma <meta> tags doesn't do us any good either, as this is purely an iOS web app problem. Caching works normally in mobile Safari, mobile Chrome, and all desktop browsers. It appears that iOS has a separate cache for apps, including web apps, that the user can not clear.

It seems that many SO users have encountered this problem, but I can't find any satisfactory solutions. Has anyone out there in a similar situation solved this problem? Could I use a manifest file to specify not to cache several files? It seems like manifest files are used to do the opposite.

Sharice answered 10/7, 2013 at 16:29 Comment(4)
confirmed still to be a (huge) problem in iOS7Bigamous
Are you using HTML Application Cache? If not, you might be able to 'trick' the iOS web-app cache into dumping the cache by creating an appcache manifest with the files you need to be updated. Then when you need to make changes and test the changes, disable the manifest by changing the name of the manifest file on your webserver. This invalidates the stored manifest and cached files because the manifest on the server can't be found.Criticaster
Not using Application Cache, nor using manifest. The web app is used in 'production' environment. It is not possible to do an update of our system somewhere in an existing installation and change a filename to trick the cache. In my development environment I can easily add some number to the filename for testing, but as OP says, it is out of the question in production environmentBigamous
I've had this as well, if I open the URL in Safari, it loads the latest JS. As soon as I add it to the Home Screen as a web app, it starts using the old JS again. Awful.Disjointed
S
6

For what it's worth, and it's not a perfect solution, we had to settle with appending query strings. I've written a shell script to make this and a few other tasks bit more automated, you can look at the source on GitHub. A few details:

  • It's designed for JS but can easily be edited to handle CSS too.
  • It takes all files listed in script_order.txt and compiles them with Google's Closure Compiler
  • Groups them into chunks under 25kb when possible (iPhone won't cache anything over 25kb pre-gzip, although apparently this extends only to browsers and not standalone webapps)
  • Outputs a PHP file with <script> tags that have a ?v=timestamp appended to the script filenames. If you're working with static HTML and can't include a PHP file, you could rewrite the output to append the script tags to your index.html file.

Another pretty hacky solution would be to save your JS/CSS with a .php file extension, and in those files set the headers to something like this:

<?php
header("content-type: application/javascript");
header('Cache-Control: no-cache');
header('Pragma: no-cache');
?>
window.alert('hello world');

EDIT:

Setting the date to 2, 3 or 4 days in the future, start the app from homescreen and then set the date back to normal also can do the trick.

Sharice answered 22/9, 2013 at 16:43 Comment(6)
Are you sure your answer has anything to do with the question? I do not know for OP but I do not have a PHP webserver. Timestamps can be added to the filenames easily using javascript. The question clearly says We're not going to go around appending the old trick ?number to the end of all our scripts, stylesheets, and images either. That's ridiculous.Bigamous
@bart-s I am the OP. Like I said, we had to settle on the query string even though I didn't want to. Of course it's easy to add timestamps with JS, but a shell script can at least help automate the deployment process across many dev systems and staging/production environments. PHP isn't necessary here. Just throwing my solution out there in case you could pick useful parts from it, but apparently that was not the case. Trust me, I feel your pain.Sharice
I must have overlooked that you're the OP. The caching is ridiculous. Even if you are able to get things ok in the browser, saving to home screen will still get the stuff from the cache. I have found another trick setting the date to future. Added to your answer to allow me delete the -1Bigamous
No worries man. It really is a shame -- we shouldn't have to resort to clever little workarounds to get something so standard to work on such a standard device. Thanks for sharing your trick, I'm going to try it out.Sharice
Setting the date to the future then back again worked a treat for me, thank you bart s :)Disjointed
Note that the date trick can be handy in development, but it won't help your users unless you expect them to do the date trick themselves.Sharice

© 2022 - 2024 — McMap. All rights reserved.