2

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:

  1. 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
  2. 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?

Community
  • 1
  • 1
Laurens Rietveld
  • 958
  • 1
  • 11
  • 21
  • I dont understand your worries about when you modify the number or permutations. Are not you deploying your servlet among your gwt compiled stuff?. Using the mgwt approach, when you modify anything and compile, static stuff includes the necessary info for the servlet to know the current permutations. In my projects it works like a charm, I did configure my web.xml and my gwt.xml files once, then every time maven compiles, it generates a .war file which I copy to my servlet container. – Manolo Carrasco Moñino Sep 11 '13 at 07:01
  • I agree using the MGWT aproach just works. The thing I have a problem with is that whenever I would update to a next version of GWT, the permutation detection script that GWT uses may change (e.g. to link a new IE version to a (optionally new) permutation). I don't want to need to change my servlet whenever I update GWT. Additionally, I prefer this solution because I cannot make the servlet perform -exactly- the same as the javascript permutation detection script, as the latter not only uses the user agent, but other dom doc properties as well. – Laurens Rietveld Sep 11 '13 at 15:59
  • I would not worry about new permutations in gwt, I trust that mgwt will be updated at the same time since mgwt maintainer is part of the gwt core team. Servlet detection is tremendously fast, it does very basic string operations. – Manolo Carrasco Moñino Sep 11 '13 at 17:15

2 Answers2

1

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:

  1. 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")
    );
    
  2. 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)

Community
  • 1
  • 1
Laurens Rietveld
  • 958
  • 1
  • 11
  • 21
  • one addition: including a manifest via iframe has as a consequence that any appcache related event handling should take place in the iframe html. Adding these event handlers to the iframe parent won't work. A solution I've used is forwarding the events from the iframe to its parents – Laurens Rietveld Oct 09 '13 at 21:59
0

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.

Manolo Carrasco Moñino
  • 9,723
  • 1
  • 22
  • 27
  • If I rephrase your comment, you're saying you are doubtful this works, right? ;) You can find a working prototype (still under development) here: http://dev.yasgui.laurensrietveld.nl . This one is tested on chrome and firefox. The fact that the original html page does not have a manifest attribute is not an issue. All you need to do is make sure you reference the original html page (the landing page) in the cache section of the manifest file as well – Laurens Rietveld Sep 12 '13 at 08:02