Consider the following problem. You'd like to serve an offline manifest/appcache file for your GWT project. In such a case, there are two issues:
- GWT generates different permutations of js files (depending on browser version). When loading the application, some GWT javascript code uses your user-agent properties to include the appropriate one. You'll want to generate a different manifest file for each of these permutations, as you don't want to cache files you won't use (and these files can be around 0.5MB per permutation). This issue is covered by the MGWT Manifest Linker, which generates different manifest files during the compilation process
- Serving the appropriate manifest file when loading the webapp in your browser
This question relates to issue 2. How can we serve this manifest dynamically, in a robust way? MGWT uses a servlet which serves the manifest, depending on the user agent from the request.
You would need to map your user agent string (e.g. Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.1)
) to a 'user-agent id' (e.g. ie6
). Using a mapping file created by the MGWT linker, you can find the manifest file to serve to the client. A major downside is that you'll need to do some simple string operations to map the complete user agent string to this user agent id with some naive string matching. You won't be able to re-use the client-side GWT code for such a mapping. (this is all discussed in this topic). As a result, whenever GWT receives an update which changes the number of permutations, and/or the supported browsers, you'll need to change your servlet code as well. In other words: this is not a robust solution.
The question is: can we serve the manifest in a different way for these GWT permutations, by serving these file dynamically on the client side?
Yes, however in a roundabit way. It is not possible to change the html 'manifest' attribute dynamically via javascript. A workaround is generating an iframe via javascript, which references an empty html page with a certain manifest attribute in it (see this topic). For this to work in GWT, you'll need to:
Change the MGWT linker, so for each permutation, you'll create an empty html page with a reference to this permutations manifest. Something like:
toReturn.add(emitString(
logger,
"<html manifest=\"" + permutation + ".manifest\"><head></head><body></body></html>",
permutation + ".manifest.html")
);
In your GWT client code, on module load: retrieve your permutation strong-name, and use this to insert the iframe for this permutation. This would look like this:
In your entry class:
public void onModuleLoad() {
appendManifestIframe(GWT.getPermutationStrongName() + ".manifest.html");
}
public static native void appendManifestIframe(String manifestIframe) /*-{
var ifrm = document.createElement("iframe");
ifrm.setAttribute("src", manifestIframe);
ifrm.style.width = 0+"px";
ifrm.style.height = 0+"px";
$doc.body.appendChild(ifrm);
}-*/;
Note that GWT.getPermutationStrongName
returns 'HostedMode' when you are in dev mode. I.e., you won't be able to use this approach in dev mode (or you should make sure you write a separete manifest/iframe for HostedMode
as well)
I'm not positive about the approach of computing the manifest file to use, in client side. Let me explain:
The manifest attribute tells to the browser that this page and all assets included in the manifest and used by this page must be cached and gotten from the cache.
If you don't set the manifest attribute in the index.html, the page would not be cached and it would not use any resource from cache.
Using the iframe approach, you would load an iframe.html with the manifest attribute set, and this manifest would include the index.html and all its assets.
I have not tested this, but I think that although the browser would cache and get the index.html from the offline storage, it would not get any asset included in it since index.html does not have the manifest attribute set, so your module.nocache.js would never be loaded if the device is offline.