• cdi
  • components
  • contexts
  • converters
  • eventlisteners
  • exceptionhandlers
  • facesviews
  • filters
  • functions
  • managedbeans
  • push
  • resourcehandlers
  • scripts
  • servlets
  • taghandlers
  • utils
  • validators
  • viewhandlers
-
  • CDNResourceHandler
  • CombinedResourceHandler
  • UnmappedResourceHandler

This ResourceHandler implementation will remove all separate script and stylesheet resources which have the target attribute set to "head" from the UIViewRoot and create a combined one for all scripts and another combined one for all stylesheets. In most cases your application's pages will load considerably. Optionally, the combined resource files can be cached on the server during non-development stage, giving your application another boost (at the expense of some heap memory on the server side).

Installation

To get it to run, this handler needs be registered as follows in faces-config.xml:

<application>
    <resource-handler>org.omnifaces.resourcehandler.CombinedResourceHandler</resource-handler>
</application>

Usage

Noted should be that the target attribute of <h:outputStylesheet> already defaults to "head" but the one of <h:outputScript> not. So if you have placed this inside the <h:head>, then you would still need to explicitly set its target attribute to "head", otherwise it will be treated as an inline script and not be combined. This is a design limitation. This is not necessary for <o:deferredScript>.

<h:head>
    ...
    <h:outputStylesheet name="style.css" />
    <h:outputScript name="script.js" target="head" />
    <o:deferredScript name="onload.js" />
</h:head>

If you want them to appear after any auto-included resources of standard JSF implementation or JSF component libraries, then move the declarations to top of the <h:body>. This is not necessary for <o:deferredScript>.

<h:body>
    <h:outputStylesheet name="style.css" />
    <h:outputScript name="script.js" target="head" />
    ...
</h:body>

The generated combined resource URL also includes the "v" request parameter which is the last modified time of the newest individual resource in minutes, so that the browser will always be forced to request the latest version whenever one of the individual resources has changed.

Caching

Optionally you can activate server-side caching of the combined resource content by specifying the below context parameter in web.xml with the amount of seconds to cache the combined resource content.

<context-param>
    <param-name>org.omnifaces.COMBINED_RESOURCE_HANDLER_CACHE_TTL</param-name>
    <param-value>3628800</param-value> <!-- 6 weeks -->
</context-param>

This is only considered when the JSF project stage is not set to Development as per Faces.isDevelopment().

This can speed up the initial page load considerably. In general, subsequent page loads are served from the browser cache, so caching doesn't make a difference on postbacks, but only on initial requests. The combined resource content is by default cached in an application scoped cache in heap space. This can be customized as per instructions in Cache javadoc. As to the heap space consumption, note that without caching the same amount of heap space is allocated and freed for each request that can't be served from the browser cache, so chances are you won't notice the memory penalty of caching.

Configuration

The following context parameters are available:

"org.omnifaces.COMBINED_RESOURCE_HANDLER_EXCLUDED_RESOURCES" Comma separated string of resource identifiers of <h:head> resources which needs to be excluded from combining. For example:
<param-value>primefaces:primefaces.css, javax.faces:jsf.js</param-value>
Any combined resource will be included after any of those excluded resources.
"org.omnifaces.COMBINED_RESOURCE_HANDLER_SUPPRESSED_RESOURCES" Comma separated string of resource identifiers of <h:head> resources which needs to be suppressed and removed. For example:
<param-value>skinning.ecss, primefaces:jquery/jquery.js</param-value>
"org.omnifaces.COMBINED_RESOURCE_HANDLER_INLINE_CSS" Set to true if you want to render the combined CSS resources inline (embedded in HTML) instead of as a resource.
"org.omnifaces.COMBINED_RESOURCE_HANDLER_INLINE_JS" Set to true if you want to render the combined JS resources inline (embedded in HTML) instead of as a resource.
"org.omnifaces.COMBINED_RESOURCE_HANDLER_CACHE_TTL" Set with a value greater than 0 to activate server-side caching of the combined resource files. The value is interpreted as cache TTL (time to live) in seconds and is only effective when the JSF project stage is not set to Development as per Faces.isDevelopment(). Combined resource files are removed from the cache if they are older than this parameter indicates (and regenerated if newly requested). The default value is 0 (i.e. not cached). For global cache settings refer Cache javadoc.

Here, the "resource identifier" is the unique combination of library name and resource name, separated by a colon, exactly the syntax as you would use in #{resource} in EL. If there is no library name, then just omit the colon. Valid examples of resource identifiers are filename.ext, folder/filename.ext, library:filename.ext and library:folder/filename.ext.

Note that this combined resource handler is not able to combine resources which are not been added as a component resource, but are been hardcoded in some renderer (such as theme.css in case of PrimeFaces and several JavaScript files in case of RichFaces), or are been definied using plain HTML <link> or <script> elements. Also, when you're using RichFaces with the context parameter org.richfaces.resourceOptimization.enabled set to true, then the to-be-combined resource cannot be resolved by a classpath URL due to RichFaces design limitations, so this combined resource handler will use an internal workaround to get it to work anyway, but this involves firing a HTTP request for every resource. The impact should however be relatively negligible as this is performed on localhost.

Conditionally disable combined resource handler

If you'd like to supply a context parameter which conditionally disables the combined resource handler, then set the context parameter "org.omnifaces.COMBINED_RESOURCE_HANDLER_DISABLED" accordingly.

<context-param>
    <param-name>org.omnifaces.COMBINED_RESOURCE_HANDLER_DISABLED</param-name>
    <param-value>true</param-value>
</context-param>
<!-- or -->
<context-param>
    <param-name>org.omnifaces.COMBINED_RESOURCE_HANDLER_DISABLED</param-name>
    <param-value>#{facesContext.application.projectStage eq 'Development'}</param-value>
</context-param>
<!-- or -->
<context-param>
    <param-name>org.omnifaces.COMBINED_RESOURCE_HANDLER_DISABLED</param-name>
    <param-value>#{someApplicationScopedBean.someBooleanProperty}</param-value>
</context-param>

The EL expression is resolved on a per-request basis.

CDNResourceHandler

If you're also using the CDNResourceHandler or, at least, have configured its context parameter "org.omnifaces.CDN_RESOURCE_HANDLER_URLS", then those CDN resources will automatically be added to the set of excluded resources.

Demo

This resource handler is also configured on this showcase web application. Rightclick the page and View Source and explore the included CSS, JS and deferred JS resources. It is recognizeable by library name omnifaces.combined. It are the following ones:

The CSS one has combined the five CSS files theme.css, primefaces.css, layout.css, showcase.css and prettify.css. The JS one has combined the five JS files jquery.js, jquery-plugins.js, primefaces.js, omnifaces.js and jsf.js. The deferred JS one has combined the two JS files prettify.js and onload.js.

Note that the PrimeFaces theme.css file can by default not be combined because it's not been added as a JSF resource, but hardcoded in PrimeFaces' HeadRenderer. There's however a way to get it to be included anyway, but this requires a custom renderer for the <head> wherein the theme name is been hardcoded as @ResourceDependency. See also Combine hardcoded PrimeFaces resources using CombinedResourceHandler. Such a HeadRenderer is also configured in this showcase.