I've got an app written with Struts/Tiles/JSP that I'm adding a GWT app to. The non-GWT portion of my app handles css caching by actually writing out the css file with a version number taken from my svn repository attached, like this "styles.css?svnbuild=12345". That way I can tell the browser to cache those css files forever and when I deploy a new version all my users download it immediately.
Now I'm moving on to the GWT app and I love how it uses "longmd5sum.cache.css" as the filename so I can still tell the browser to cache it forever. The problem is that the css files associated with my theme, like "gwt-standard.css", don't have a strong name and don't have my svnbuild parameter attached. Whenever I deploy a new version of my app, users are still seeing the old version of the css which makes it look wrong.
Has anyone figured out a best practice for handling caching of gwt theme css files? Is there a way I can append an svnbuild parameter or something similar when appending the css to the document?
Adding a version parameter when importing stylesheet All you need to do is add a version URL parameter to the end of your href like so ? version=1 . The browser will notice the new version and stop caching the stylesheet. All changes in your stylesheet will be reflected in your browser.
When the browser parses this HTML, it identifies that a CSS resource needs to load from https://www.example.com/app.css. The browser issues a request to the server for this file, the server returns the file and also tells the browser to cache it for 30 days.
Ok. So after I posted this I dug into the GWT source code and found some links about creating a GWT custom linker.
http://development.lombardi.com/?p=29
http://code.google.com/webtoolkit/doc/1.6/DevGuideOrganizingProjects.html
Here's how I solved it with my own linker. First I made a linker class that extends the standard IFrameLinker:
@LinkerOrder(LinkerOrder.Order.PRIMARY)
public class MyLinker extends IFrameLinker {
protected String generateStylesheetInjector(String stylesheetUrl) {
stylesheetUrl = stylesheetUrl + "?buildtime=" + System.currentTimeMillis();
return super.generateStylesheetInjector(stylesheetUrl);
}
}
After that it's just a matter of telling your module to use your custom linker. In your module.gwt.xml file:
<module>
<define-linker name="mylinker" class="com.company.gwt.core.linker.MyLinker" />
<add-linker name="mylinker" />
</module>
Just tried it out and now in my nocache.js file it outputs a new timestamp every time I compile. My users can cache the css file forever and they will download a new one automatically whenever I deploy a new version of the app.
Seems like the preferred thing to do now is to use ClientBundles rather then separate CSS: Google Css Resource Cookbook . We recently made this transition quite painlessly with the following (with obviously some future intent to eliminate the @CssResource.NotStrict annotation):
public interface OurCssResources extends ClientBundle {
@Source("ourCSS.css")
@CssResource.NotStrict
public CssResource getCss();
...
Then in the root of our application:
private void injectAllCss() {
OurCssResources resources = GWT.create(OurCssResources.class);
resources.getCss().ensureInjected();
...
This is kind of a heavy handed approach, but it solves the problem, and it puts you on the road to doing things the google intended way.
It looks like you can get even closer to their intended way fairly automatically (although I haven't tried these on 2.4, the stuff I mentioned above did work under 2.4 (I did have a problem with an external dependency (GXT); but since that won't change i just left it using the old fashioned method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With