#summary Compile-time resource optimizations
= Introduction =
The resources in a deployed GWT application can be roughly categorized into resources to never cache `.nocache.js`, to cache forever `.cache.html`, and everything else `myapp.css`. The ClientBundle interface moves entries in the everything-else category into the cache-forever category.
= Goals =
* No more uncertainty if your application is getting the right contents for program resources.
* Decrease non-determinism caused by intermediate proxy servers.
* Enable more aggressive caching headers for program resources.
* Eliminate mismatches between physical filenames and constants in Java code by performing consistency checks during the compile.
* Use 'data:' URLs, JSON bundles, or other means of embedding resources in compiled JS when browser- and size-appropriate to decrease the number of round-trips entirely.
* Provide an extensible design for adding new resource types.
* Ensure there is no penalty for having multiple ClientBundle resource functions refer to the same content.
= Non-Goals =
* To provide a file-system abstraction
= Examples =
To use the ClientBundle, add an inherits tag to your `gwt.xml` file:
{{{
}}}
Interfaces:
{{{
public interface MyResources extends ClientBundle {
public static final MyResources INSTANCE = GWT.create(MyResources.class);
@Source("my.css")
public CssResource css();
@Source("config.xml")
public TextResource initialConfiguration();
@Source("manual.pdf")
public DataResource ownersManual();
}
}}}
You can then say:
{{{
Window.alert(MyResources.INSTANCE.css().getText());
new Frame(MyResources.INSTANCE.ownersManual().getURL());
}}}
= I18N =
ClientBundle is compatible with GWT's I18N module.
Suppose you defined a resource:
{{{
@Source("default.txt")
public TextResource defaultText();
}}}
For each possible value of the `locale` deferred-binding property, the ClientBundle generator will look for variations of the specified filename in a manner similar to that of Java's `ResourceBundle`.
Suppose the `locale` were set to `fr_FR`. The generator would look for files in the following order:
# default_fr_FR.txt
# default_fr.txt
# default.txt
This will work equally well with all resource types, which can allow you to provide localized versions of other resources, say `ownersManual_en.pdf` versus `ownersManual_fr.pdf`.
= Pluggable Resource Generation =
Each subtype of `ResourcePrototype` must define a `@ResourceGenerator` annotation whose value is a concrete Java class that extends `ResourceGenerator`. The instance of the `ResourceGenerator` is responsible for accumulation (or bundling) of incoming resource data as well as a small degree of code generation to assemble the concrete implementation of the ClientBundle class. Implementors of `ResourceGenerator` subclasses can expect that only one `ResourceGenerator` will be created for a given type of resource within an ClientBundle interface.
The methods on a `ResourceGenerator` are called in the following order
# `init` to provide the `ResourceGenerator` with a `ResourceContext`
# `prepare` is called for each `JMethod` the `ResourceGenerator` is expected to handle
# `createFields` allows the `ResourceGenerator` to add code at the class level
# `createAssignment` is called for each `JMethod`. The generated code should be suitable for use as the right-hand side of an assignment expression.
# `finish` is called after all assignments should have been written.
`ResourceGenerators` are expected to make use of the `ResourceGeneratorUtil` class.
= Potential pitfalls =
* Changing the content of the resources will change the filenames (or data: encoding), thus forcing a recompile of the GWT application. To avoid this, the inlining and renaming features can be globally toggled off in your gwt.xml file during the development phase.
* Inlining files into the compiled JS may not make sense if those files are not always accessed by the program, thus inlining should be configurable on a per-resource or per-ClientBundle basis.
= Levers and knobs =
* `ClientBundle.enableInlining` is a deferred-binding property that can be used to disable the use of `data:` URLs in browsers that would otherwise support inlining resource data into the compiled JS.
* `ClientBundle.enableRenaming` is a configuration property that will disable the use of strongly-named cache files.
= Resource types =
* CssResource
* DataResource
* ExternalTextResource
* GwtCreateResource
* ImageResource
* TextResource
= Migrating from !ImmutableResourceBundle =
== Plan ==
* Expected that incubator IRB system will initially co-exist with ClientBundle in trunk while integration issues are worked out.
* Will then change incubator code to add deprecations.
* No plans to remove types from incubator for _long period of time_.
* No additional features or bug-fixes will be added to incubator APIs.
== Changes ==
* Package changed to `com.google.gwt.resources`
* Inherit `com.google.gwt.resources.Resources`
* Renamed `ImmutableResourceBundle` to `ClientBundle`
* Renamed `@Resource` annotation to `@Source`
* Map-style methods moved to `ClientBundleWithLookup`
* Switched most gwt.xml properties to be configuration properties instead of deferred-binding properties
* Some `gwt.xml` properties have changed names:
* `ResourceBundle.*` to `ClientBundle.*`
* `CssResource.enableMerge` to `CssResource.mergeEnabled`
* `CssResource.forceStrict` to `CssResource.strictAccessors`
* `CssResource.globalPrefix` to `CssResource.obfuscationPrefix`
* `CssResource.style` has changed to a configuration property; switch from `` to `` tags to configure this.
* StyleInjector moved to `com.google.gwt.dom.client` package