What's with all the cache/nocache stuff and weird filenames?
During its bootstrap process, a Google Web Toolkit application goes through a series of sometimes oddly-named files. These files, generated by the GWT Compiler, usually seem strange to new users. To effectively deploy a GWT application, however, it is necessary to understand these files so that they can be placed appropriately on the web server.
The sets of files produced by the GWT 1.3 and GWT 1.4 compilers are slightly different, so we will treat them separately here to explain what roles these files play in each of their respective sets.
In GWT 1.3, the important files produced by the GWT Compiler are:
gwt.js
.nocache.html
*
<Alphanumeric>
.cache.html
In GWT 1.4, the important files produced by the GWT Compiler are:
* The same as above, since GWT 1.4 supports the GWT 1.3 bootstrap model and uses similar sets of application files for the 1.4 model.
* .nocache.js
(or -xs.nocache.js
for cross-site script inclusion)
*
<Alphanumeric>
.gwt.rpc
Each of the items above is described below. However, first it's important to understand Deferred Binding since that notion is at the heart of the bootstrap process, so you might want to read this link before continuing.
Before explaining what each file does, it's useful to summarize the overall bootstrap procedure for a GWT 1.3 application:
- The browser loads and processes the host HTML page.
- When the browser encounters the page's
<script src="gwt.js">
tag, it immediately downloads and executes the JavaScript code in the file. - gwt.js scans the host page's DOM, looking for a
<meta>
tag with 'name' attribute set to "gwt:module". gwt.js fetches the name of the GWT module to load from the "content" attribute. - gwt.js constructs a URL to a new filename, using the pattern:
<Module Name from Meta Tag>.nocache.html
. For example, if your module iscom.company.app.MyApp
, thengwt.js
will look forcom.company.app.MyApp.nocache.html
. - gwt.js then creates a hidden
<iframe>
, inserts it to the host page's DOM, and loads the.nocache.html
file into that iframe. - The
.nocache.html
file contains JavaScript code that resolves the Deferred Binding configurations (such as browser detection, for instance) and then uses a lookup table generated by the GWT Compiler to locate one of the.cache.html
files to use. - The
.nocache.html
file then does a location.replace() call, replacing itself with the chosen.cache.html
file. - The
.cache.html
file contains the actual program logic of the GWT application.
The bootstrap procedure for a GWT 1.4 application is slightly different, and goes as follows:
- The browser loads and processes the host HTML page.
- When the browser encounters the page's
<script src="<Module Name>.nocache.js">
tag, it immediately downloads and executes the JavaScript code in the file. - The
.nocache.js
file contains JavaScript code that resolves the Deferred Binding configurations (such as browser detection, for instance) and then uses a lookup table generated by the GWT Compiler to locate one of the.cache.html
files to use. - The JavaScript code in
.nocache.js
then creates a hidden<iframe>
, inserts it to the host page's DOM, and loads the.cache.html
file into that iframe. - The
.cache.html
file contains the actual program logic of the GWT application.
That's the process in a nutshell. The sections below describe each of the GWT 1.3 application files in detail.
The gwt.js File
The gwt.js file is comparatively simple. It is a small amount of meticulously cross-browser JavaScript code that kicks off the GWT startup procedure. If you are familiar with operating systems, you can think of gwt.js as a sort of bootloader. Its responsibility is to scan the host HTML page and gather the information required to locate the next phase in the bootstrap process. Generally this boils down to seeking the <meta>
tag that identifies the GWT Module containing your application.
It is possible to specify multiple GWT Modules in a single HTML host page. The gwt.js code is intended to handle this case, but it is a somewhat rare use case.
The .nocache.html File
The "nocache" file is where Deferred Binding occurs. Before the application can run, any dynamically-bound code must be resolved. This might include browser-specific versions of classes, the specific set of string constants appropriate to the user's selected language, and so on. In Java, this would be handled by simply loading an appropriate service-provider class that implements a particular interface. To maximize performance and minimize download size, however, GWT does this selection up-front in the "nocache" file.
If you were to look inside a .nocache.html
file, you would see that it is JavaScript code wrapped in a thin HTML wrapper. You might wonder why the GWT Compiler doesn't simply emit it as a JavaScript .js file. The reason for this is that certain browsers do not correctly handle compression of pure-JavaScript files in some circumstances. This would effectively mean that users unfortunate enough to be using such a browser would download the .js file uncompressed. Since the GWT mantra is no-compromise, high-performance AJAX code, the GWT Compiler wraps the JavaScript in an HTML file to wiggle around this browser quirk.
The reason the file is named ".nocache.html" is to indicate that the file should never be cached. That is, it must be downloaded and executed again each time the browser starts the GWT application. The reason it must be re-downloaded each time is that the GWT Compiler regenerates it each time, but under the same file name. If the browsers were allowed to cache the file, they might not download the new version of the file, when the GWT application was recompiled and redeployed on the server. To help prevent caching, the code in gwt.js
actually appends an HTTP GET parameter on the end of file name containing a unique timestamp. The browser interprets this as a dynamic HTTP request, and thus should not load the file from cache.
One of the key features of the "nocache" file is a lookup table that maps Deferred Binding permutations to .cache.html
filenames. For example, "Firefox in English" and "Opera in French" would both be entries in the lookup table, pointing to different .cache.html
files.
The .cache.html Files
The "cache" files contain your application's logic. Like the "nocache" file -- and for the same reason -- the "cache" files are HTML rather than pure JavaScript.
They are named according to the MD5 sum of their contents. This guarantees deterministic behavior by the GWT Compiler: if you recompile your application without changing code, the contents of the output will not change, and so the MD5 sums will remain the same. Conversely, if you do change your source code, the output JavaScript code will likewise change, and so the MD5 sums and thus the filenames will change.
Because of this uniqueness guarantee, it is safe (and indeed preferable) for browsers to cache these files, which is reflected in their .cache.html
file extension.
In GWT 1.4, there are additional files produced which are important for the GWT 1.4 bootstrap model and new java.io.Serializable
support in GWT RPC. These are detailed below:
The .nocache.js File
The .nocache.js
file subsumes the functionality of the gwt.js and .nocache.html files in the 1.3 bootstrapping model. That is, in the GWT 1.4 boostrapping model, the .nocache.js
file is now where Deferred Binding occurs, including the scanning of the host HTML page and picking the right `.nocache.html' application file according to the client's browser environment. The new bootstrapping procedure makes one less HTTP roundtrip call to load your GWT application, which presents a substantial improvement in application load time.
The .gwt.rpc File
In previous versions of GWT, if your application used GWT RPC, the types that you wanted to serialize across the wire had to implement the IsSerializable
interface. In GWT 1.4, types that implement the java.io.Serializable
interface now also qualify for serialization over RPC, with some conditions.
One of these conditions is that the types that you would like to serialize over the wire must be included in the .gwt.rpc file generated by the GWT compiler. The .gwt.rpc file serves as a serialization policy to indicate which types implementing java.io.Serializable
are allowed to be serialized over the wire. For more details on this and other conditions to use Serializable
types in GWT RPC, check out this FAQ.
Summary
That is the story behind the somewhat strange GWT file names. There is indeed a method to the madness: In GWT 1.3, gwt.js loads the nocache file for Deferred Binding resolution, and the nocache file selects a cache file based on the execution context. In GWT 1.4, the .nocache.js
file both performs Deferred Binding resolution and selects the cache file based on the execution context.