When you run a ADF Faces 11g Rich Client components application, you (or rather your users) are hit with a substantial JavaScript download overhead. It is not surprising, given the richness of the component library. However, especially for internet applications targeted at external users – consumers, customers – it may be very undesirable to have them wait up to several seconds for this download to complete.
The default splash-page that displays during the load of the Javascript surely looks familiar. (note: the resources section of this article has a reference to an article by Frank Nimphius that explains how to get rid of the splash-page -or modify it-; however, that does not take away the download overhead itself unfortunately).
Especially if the first page in the web application does not really use all that much richness to begin with. It is not uncommon to have a homepage that is largely static, pretty and heavily styled through CSS with perhaps a global search item, a couple of navigation links or buttons and maybe some newsfeeds or special offers. Or to start the application with a fairly simple login page.
This article describes how to reduce the (initial) download size to have the first page in an ADF 11g Rich Client Faces application display much more rapidly.
I am wondering whether I can create an ADF application that has pages using the Rich Client Components but also a first page – home page, login page – that loads quickly, without the overhead of the JavaScript resources. What if the first page is a plain JSF or Trinidad based page, perhaps it could load without most of the Rich Client JS. I could perhaps even have this first page contain a hidden iframe that loads a rich ADF Faces page with the JavaScript resources to make them available to subsequent pages.
The Firebug overview of resources loaded for a plain ADF 11g Rich Web Application Page:
The all-11.1…….js resource you see listed has an uncompressed size of 2 Mb. In this example, running the application locally, it takes about 800 ms to download the library. Over a WAN or DSL connection, that time may increase to several seconds.
The simple Built In solution: partitioning the JavaScript libraries
As it turns out, things are much easier than any home grown workaround. We do not need to create a home page that does not use rich components to prevent the 2 Mb download. We do not have to create a servlet filter that prevents the big chunk from being downloaded for the home page. There is a much neater facility in ADF 11g – though currently somewhat undocumented.
Through setting a Context Parameter in the web.xml file, we can tell ADF to attach JavaScript resources to pages as ‘required’. This means that depending on the components used in a page, only certain sections (partitions) of the JavaScript resources are download with the page. A page with only a button requires maybe 2% of the overall chunk of JS libraries (on top of the core chunk that is needed for bootstrapping and AJAX-ifying the page) while a page with full blown drag & drop, popup and other richness may need almost all of it.
It turns out there are three servlet context parameters we can configure in the web.xml of an ADF application that each have their own impact on the size of the Javascript resources and the manner (timing, granularity) in which they get downloaded.
When I configure these three parameters like this:
<context-param> <param-name>org.apache.myfaces.trinidadinternal.DISABLE_CONTENT_COMPRESSION</param-name> <param-value>false</param-value> </context-param> <context-param> <param-name>oracle.adfinternal.view.rich.libraryPartitioning.ENABLED</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT</param-name> <param-value>false</param-value> </context-param>
the download hit for the same page I analyzed before has been reduced dramatically:
The first parameter – org.apache.myfaces.trinidadinternal.DISABLE_CONTENT_COMPRESSION – governs whether the JavaScript resource are served in a compressed (zipped) fashion; this reduces the download size by a factor of four or more. The third parameter activates (or deactivates) a JavaScript obfuscator that reduces the size of the code by removing comment, rewriting variable-names to the shortest possible etc. The code becomes completely unreadable but will still function. And is much smaller in size.
The second parameter – oracle.adfinternal.view.rich.libraryPartitioning.ENABLED – is the really interesting one. When turned on (parameter value is true), it instructs ADF to not associate the full chunk of JavaScript resources to the first page in the application. Instead, the page (component tree) is analyzed to determine which components are used in the page. Component authors have specified which JavaScript chunks are required for their component. Using these two pieces of information, ADF knows which granular JS resources to associate with a page, and only those are downloaded.
Here we see an example of a page that only contain a inputRangeSlider and an inputNumberSpinbox. Instead of downloading the full chunk of ADF Faces RichClient Components JavaScript, due to the libraryPartitioning setting, the first page requests targeted small chunks of component specific JavaScript.
Of course there is some overhead in serving several smaller resources instead of only one; but if the combined size is very much smaller than the alternative very large one (30 Kb vs. 400 Kb) than it is quite possibly very much worth experimenting with.
Note: this functionality is at the present somewhat experimental, undocumented and probably unsupported. However, for anyone with qualms as to whether ADF 11g Rich Client Components can be used for internet applications, this clearly shows how Oracle are going to address this particular issue. I am convinced that in a release in the near future this functionality is fully supported and will enable us to bring our internet application into production with minimal JS overhead. Thanks to obfscation, compression and JS partitioning.
Resources
Thanks to Daan Horn for working together on this. Thanks to Frank Nimphius, Didier Laurent and Duncan Mills for their contributions.
Andy Schwartz on JavaScript Library Partitioning and Compression & Obfuscation.
Frank Nimphius on Configuring a default Splash page for ADF 11g applications
You should delete internal from trinidadinternal. The first parameter is org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION and not org.apache.myfaces.trinidadinternal.DISABLE_CONTENT_COMPRESSION
Dimitar – you are quite right. I misinterpreted the DISABLE_CONTENT_COMPRESSION parameter. Thanks for pointing this out to me.
Lucas
In my opinion there is a mistake in this article. The parameter org.apache.myfaces.trinidadinternal.DISABLE_CONTENT_COMPRESSION does not affect zipping of the response content. As it documenation says it only instructs the server to rewrite the names of cascading styles in the generated HTML output in order to decrease names lengths.
If somebody needs to compress (e.g. to zip) the content of downloaded JavaScripts and CSS from a WebLogic 10.3 server, then she has to use a servlet filter that performs that compression (as the WebLogic server does not provide built-in module for compression). Implementation and usage of such filter is quite simple, I used a ready-for-use filter that I downloaded from http://ftpna2.bea.com/pub/downloads/Gzipfilter_war.zip