iOS Web App - how to deal with overzealous app caching? - iphone

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.

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.

Related

Live manipulation to a Localhost Webpage or a Local Html File in Flutter

How can I show a HTML+CSS file in a Flutter widget, while being able to manipulate the HTML or CSS (in file) and viewing the changes live?
Manipulating HTML:
I could use JavaScript to manipulate the HTML DOM of a loaded webpage, probably through localhost? Is there a better way to do it instead?
Manipulating CSS:
Searching around the internet I find JavaScript like "dom.getElementById('something').style.color = color.red". Though, how could I go for loading css on every change of the css file, if possible?
I hope my question is not vague. Please let me know of any issues or suggestions on this question.
The app is meant for desktop installs, though I wouldn't mind switching to working with flutter-web if need be.
Kind regards.

Copying images in from anti-scraper websites. Google Docs handles it easily - anyone know how?

I've been playing around with making a draftjs plugin that lets the user paste in mixed text&image content from websites and have images auto-uploaded to the server. I've quickly come to the realization that it's not easy, simply because of how many different sites use different kinds of counter-measures for copy/pasting images. Standard image tags in page content are no problem - easily grab the src and handle the file upload from the url. However, many sites use all kinds of trickery to make this a pain. For example, some will only serve small thumbnails, requiring a GET request on the image with a hash key in order to retrieve a larger version. Others somehow seem to corrupt the image so that it's unreadable by the time it's been retrieved. Others still play with weird embed tags to mess with draftjs' image blocks.
But then I open up a Google Docs file, and find that when I copy any images into that from a website, there's never any troubles whatsoever. All the problematic websites that I'm finding myself having to write specific methods for retrieving from seem to be handled by Google Docs with ease.
Am I using completely the wrong approach by trying to retrieve images from a url? Does Google use a far superior approach (yes, I presume) - in which case, does anyone have any idea what that approach might be?

How to upload an image with jquery in all browsers

I am currently creating a form that involves a file uploader. Currently
my form is fine just using multipart and post but later on in future iterations
it will be necessary for the form to be posted with ajax in order to edit the
image before submitting the form.
I have seen a lot of things about multiple files like jquery-file-upload and swf
and php with uploadify and a whole host of non IE 7+ solutions. However those are
not going to work for this specific project and I am really just looking for the bare
bones nothing fancy to have to deal with just sends the image data to an endpoint.
What is the best way to do this in a way that can support all browsers.
=====EDIT=====
I havent tested this completely yet but this solution seems good to me
https://github.com/francois2metz/html5-formdata
Fine Uploader is a library that provides the ability to support cross-browser uploading. Ajax/xhr post requests are used for all browsers that support the file api. Otherwise, a form-based upload method is used. No flash is used or needed. This is all transparent to the user. Check out fineuploader.com for more details.
You can't send file through AJAX request this is just impossible. If you use HTML5 File API that would work but as you stated in your question you need to support old browsers. So I think you either have to use flash (uploadify uses flash as well) or you don't have any other option.
You can have a look at this question/answer:
jQuery Ajax File Upload

Presenting a website locally and offline in iOS

I am developing an application for a client where a requirement is that a series of complex (multi-file, JS, CSS, etc), websites must be presented offline, without any web connection required at all.
So I have all of the HTML content folders, and can add them into my XCode project... but now I need to show them.
The UIWebView is fine when you just have one HTML file... but the relative paths for the JS and CSS do not translate over.
What is the best way to do this. I've seen a couple of potential choices. One way is to run a super basic web server locally, dump all the files into /documents (or thereabouts) and serve it from there... the second is to somehow make UIWebView re-interpret the paths so that they point to the right place locally... which I am not sure if it's possible but I've seen it alluded to.
Seems like a lot of people just cover loading a single UIWebView page, and not so much discussing how to deal with CSS/JS dependencies.
Anyone have any bright ideas, links, etc?
Thanks
I think that if you add your HTML/CSS/JS tree to your Xcode project and select "Create folder references for any added folder" (instead of "Recursively create groups for any added folders"), then your bundle will contain the HTML/CSS/JS folder hierarchy (instead of the flattened-out list of all files). This would preserve relative paths.
As to the "reinterpreting" point, you can define
– webView:shouldStartLoadWithRequest:navigationType:
in your UIWebViewDelegate to intercept any attempt at loading any file. There you can change the url on the fly.
Also, have a look at this interesting article by Rob Napier: Drop-in offline caching for UIWebView.

Deploy GWT Application as Single JavaScript File

The compiled JavaScript output of a GWT application is divided into various files, for instance
*.cache.html
*.gwt.rpc
hosted.html
*.nocache.js
...
I know this is done with the purpose of minimizing the size of the JavaScript, which has to be downloaded by users. For instance so that a Firefox user does not have to load the JavaScript specifically compiled for IE6.
However, especially for small GWT applications it might often be faster to download a single file of say 500kb rather than make two sequential requests first for the 5kb *.nocache.js script and then for the rest of the app (cache.html files, etc.).
This leads me to the question: Is there any framework or procedure to bundle the output of the GWT compiler into a single JavaScript file?
First, you can merge all permutations in a single file by using so-called "soft permutations".
Then, you can inline your *.nocache.js into the HTML host page (e.g. using a JSP's #include directive) to cut one additional request (you might have to add a <meta name=gwt:property content='baseUrl=myapp'> where myapp is the subfolder where the .nocache. files are located).
AFAIK that's what Google are doing for their GWT apps.
Alternatively, you can run the permutation selection on the server-side if you can totally replace the selection script (*.nocache.js) with server-side content negotiation (based on User-Agent and Accept-Language request headers for instance) that can directly generates a <script> tag for the appropriate *.cache.js file (provided you use the xsiframe linker).
AFAIK, Google use all these techniques for their GWT apps (such as Google Groups). For a small app, though, I'm not sure it's worth the effort…
Also, the last two techniques work best when your HTML host page is already dynamic and therefore already non-cacheable; otherwise you're mostly moving the problem, not solving it.
I wonder whether the sso linker can be used when you collapse all properties and soft-permutations down to a single hard permutation.
Yes, but it's maybe not something you want. See this answer: https://stackoverflow.com/a/4453716/66416 to this stackoverflow question: Merge GWT generated files.
I found another way to accomplish this: Writing a custom Linker for GWT. Two examples for linkers which compile into a single JavaScript file are:
GwtNodeLinker.java from Gwt Node project
ServerSingleScriptLinker.java from Env.js project