Components and control (or lack thereof)
If you have components in the data table that generate embedded JavaScript, there isn't much you can do except plead with the author of the component library to keep the encoded output terse. This is unfortunately one of the areas of control that you relinquish by choosing to use a component-based approach. My advice here is to submit patches to correct waste or use your own components.
I did discover one area in Ajax4jsf where you can cheat. Previously, I recommended using <a:commandLink> for defining Ajax interactions. But in Ajax4jsf, it's possible to turn any JavaScript event on the page into an Ajax request using the <a:support> tag, making it a drop-in replacement for <a:commandLink>. And it just so happens that the JavaScript that the <a:support> tag produces is smaller than the JavaScript generated by the <a:commandLink>. Here's how the edit link would look using <a:support> rather than <a:commandLink>:
<h:graphicImage id="e" value="/i/e.png" alt="Edit" title="Edit"
rendered="#{_item != conversationScope.get('itemInEditMode')}">
<a:support id="ec" event="onclick" action="#{benthicMsmntEditor.editItem}"
reRender="dataTable" ajaxSingle="true"/>
</h:graphicImage>
Not only does switching to <a:support> reduce the size of the response, but it also requires less processing on the server, according to my tests.
Curbing the expressiveness of CSS
RichFaces uses a well-designed approach to styling components by relying heavily on CSS. This design allows for styles to be extracted into external stylesheets and shared by all instances of a component. However, the creators of RichFaces went a bit overboard by using two style classes per component, an internal name and a public name, and making the name of these classes excessively long. As an example, here is a table row with one cell shown in a RichFaces data table.
<tr class="dr-table-firstrow rich-table-firstrow ">
<td id="dc:dt:1:tx"
<class="dr-table-cell rich-table-cell">Diptera
</td>
</tr>
You need some style classes or else your page is going to look pretty plain, but this is a tad overkill. The solution here is to disable the public class name and just reference the internal class name in your custom stylesheet. After all, the first word in CSS is cascading, which means you can override the styles that RichFaces associates with a class. There is no need for two style classes. To apply this optimization, you have to alter the RichFaces UI source files to remove the appending of the public class name, and recompile the library. If you are patient, you can wait for a future release of RichFaces which will likely implement this optimization (my guess is that the public class will remain and the internal class removed).
Overall, our changes have significantly reduced the size of the response. But there is one major outstanding issue remaining. If you crack open FireBug and inspect the response of one of the Ajax requests, you will see the following markup in the <head> of the response:
<head><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAcss/toolBar.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" /><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg.ajax4jsf.javascript.PrototypeScript"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg.ajax4jsf.javascript.AjaxScript"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAscripts/menu.js"></script><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAcss/dropdownmenu.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" /><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/scripts/utils.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg/ajax4jsf/javascript/scripts/form.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/scripts/form.js"></script><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAcss/menucomponents.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" /><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/css/msg.css" /><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/css/msgs.css" /><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg.ajax4jsf.javascript.ImageCacheScript"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/scripts/browser_info.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAscripts/simpleTogglePanel.js"></script><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAcss/simpleTogglePanel.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" /><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/scripts/jquery/jquery.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/scripts/available.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg.ajax4jsf.javascript.SmartPositionScript"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/scripts/scriptaculous/effects.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAscripts/suggestionbox.js"></script><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAorg/richfaces/renderkit/html/css/suggestionbox.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" /><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAscripts/comboboxUtils.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAscripts/combolist.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAscripts/inplaceinput.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAscripts/inplaceselectlist.js"></script><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAscripts/inplaceselect.js"></script><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAcss/inplaceselect.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" /><script type="text/javascript" src="/edas2-perflab/a4j/g/3_2_2.GAorg/richfaces/renderkit/html/scripts/data-table.js"></script><link class="component" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAcss/table.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" /><link class="user" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAextended-skin-styles.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" /><link class="user" rel="stylesheet" type="text/css" href="/edas2-perflab/stylesheet/theme.css" /></head>
Whoa! What's with all of those JavaScript and CSS includes?? Again, this delves deeply into how RichFaces is implemented. RichFaces bundles CSS and JavaScript with each component and includes them in any page that uses that component. Since JSF allows the component tree to be modified dynamically in Java, it's possible for the components that appear on the page to be changed during a postback. That means new resources may be needed. To accommodate this scenario, RichFaces sends the stack of CSS and JavaScript includes with each response so that the page can be updated as needed. (Truthfully, RichFaces could be optimized to send just the new resources).
As mentioned earlier, HTTP connections are costly and this piecemeal approach is not in tune with performance concerns. To get around this problem, RichFaces can pack all the JavaScript and CSS in its component set and deliver them in two requests on the very first page in the application and ensure that the browser caches them on all future requests. To enable this feature, add the following two context parameters to the /WEB-INF/web.xml file:
<context-param>
<param-name>org.richfaces.LoadStyleStrategy</param-name>
<param-value>ALL</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.LoadScriptStrategy</param-name>
<param-value>ALL</param-value>
</context-param>
Frankly, you would be crazy not to use these settings in a production environment. Here's the <head> tag that RichFaces rewards you with on an Ajax request.
<head>
<link class="user" rel="stylesheet" type="text/css" href="/edas2-perflab/a4j/s/3_2_2.GAextended-skin-styles.xcss/DATB/eAGbfKFwr7PCCWUAE8YD4A__" />
<link class="user" rel="stylesheet" type="text/css" href="/edas2-perflab/stylesheet/theme.css" />
</head>
The only reason the <head> tag contains anything at all now is because we are using two custom stylesheets in our application. RichFaces doesn't roll up custom resources into its pack and thus doesn't exclude them. (It's possible that there's a way to get RichFaces to stop including custom stylesheets in an Ajax response, but I haven't figured it out yet).
Page:
1
2
3
4