Many of us use Sencha GXT and GWT to help our teams produce structured, powerful, and maintainable web applications. With Dev Mode and Super Dev Mode, we can easily write Java and test how it behaves in the browser. The Compiler then produces optimized code to run in our users’ browsers.
It turns out that the compiler is customizable, and can be instructed to change its output based on your needs, to produce a better build. What is a better build though? This definition will change based on the project, and based on the team member. For many developers, the best build is the one that happens as fast as possible, letting you get straight to testing. For some teams, the best build is often the one that produces the smallest browser download, or sometimes the smallest total compiled size.
In this article, we’ll discuss several different ways to customize what the compiler is building for you, and how it can impact build times and output sizes. We’ll use the Sencha GXT Explorer as an example. While it is not as complex as many applications out there, it does use almost every single widget Sencha GXT has to offer. Using Sencha GWT 2.4.0 and GXT 3.0.4, the Explorer builds in about 183 seconds, and the largest permutation is 2,608,783 bytes.
A ‘normal’ build is one where you get 6 basic permutations, one for each category of browser. These have been selected by the GWT team as related enough to always treat as the same. These browsers are:
- Firefox, all versions
- All Webkit browsers (Safari, Chrome, Android Browser, etc)
- IE6 and IE7
- IE9 (and IE10)
GXT is configured by default to use these same 6 permutations — it is a good middle ground between all possible configurations and lumping everything together. GXT adds several possible browsers that are not normally listed — IE6 and IE7 are kept apart, as are IE9 and IE10. Chrome and Safari are treated as two different browsers, with several distinct versions, where required. Firefox is lumped into two categories — before Gecko 1.9 and after, allowing for some tests of specific cases. GXT also adds another degree of possibility — Operating System. There are unique features to each OS that make it important to allow GXT to tell the difference.
With all of these variations in the build, it’s possible to end up with 52 permutations in 3.0.4! This makes the build times much longer than the normal 6 permutations — but do we gain anything?
To test this question, I made a few changes to the application’s module file. Instead of
<inherits name="com.sencha.gxt.ui.GXT" />
which is the standard inherits statement to load GXT, I replaced this statement with the specific modules we were interested in. We can load just the widgets and the State handling code instead, as well as a theme:
<inherits name="com.sencha.gxt.widget.core.Core" /> <inherits name="com.sencha.gxt.state.State" /> <inherits name="com.sencha.gxt.theme.blue.Blue" />
At present, Charts do not allow for this particular change, so I had to make the same change to the Charts.gwt.xml file to allow it to make this change overall.
This is a massive overkill and doesn’t save us much. The largest permutation is now down to 2,587,780 bytes — a difference of about 21K, or a savings of less than 1%, and the build took 20 minutes, up from about 3 minutes. Interestingly, it also only produced 26 actual permutations — while the OS check allows our code to differentiate between Windows/Mac/Linux/Unknown, it turns out that we rarely need to take advantage of this check, so half of our build time is essentially wasted. We’re still seeing savings though — some teams may find it worthwhile to create very specific builds for supported browsers, then limit which browsers they support when debugging and allow very long builds for production.
We can also take this in the other direction in two different ways by combining browsers into fewer permutations or by limiting which browsers we intend to support.
First, we can restrict which browsers we intend to support:
<inherits name="com.sencha.gxt.ui.GXT" /> <set-property name="gxt.user.agent" value="ie9, ie10, gecko1_9, safari5, chrome, opera" />
By inheriting GXT again, and limiting the browsers we are most interested in, we are limiting the build down to 4 permutations — ie8, ie9/ie10, gecko1_9, and safari5/chrome. These 6 browsers only require 4 permutations because once again, we are condensing similar browsers into the same build. By following the previous step (not inheriting GXT directly), we can expand this back to 6 if we wanted — and be slightly more specialized than we were to begin with. Or, we can keep our smaller set. With this smaller set, we can compile in about 140 seconds, and the largest of our four permutations is 2,608,785 bytes, about the same as we started.
The second option is to further condense supported browsers into fewer permutations. There are two tools for this option and both rely on the idea of merging permutations. First, we can specify that one or more property should be collapsed:
<inherits name="com.sencha.gxt.widget.core.Core" /> <inherits name="com.sencha.gxt.state.State" /> <inherits name="com.sencha.gxt.theme.blue.Blue" /> <set-property name="gxt.user.agent" value="ie9, ie10, gecko1_9, safari5, chrome, opera" /> <!-- merge gecko1_9, safar5, and chrome into one permutation --&