- java.lang.Object
-
- jakarta.faces.application.ResourceHandler
-
- jakarta.faces.application.ResourceHandlerWrapper
-
- org.omnifaces.resourcehandler.DefaultResourceHandler
-
- org.omnifaces.resourcehandler.CombinedResourceHandler
-
- All Implemented Interfaces:
FacesListener
,SystemEventListener
,FacesWrapper<ResourceHandler>
,EventListener
public class CombinedResourceHandler extends DefaultResourceHandler implements SystemEventListener
This
ResourceHandler
implementation will remove all separate script and stylesheet resources which have thetarget
attribute set to"head"
from theUIViewRoot
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 itstarget
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:criticalStylesheet>
nor<o:deferredScript>
.<h:head> ... <h:criticalStylesheet name="layout.css" /> <h:outputStylesheet name="page.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 Faces implementation or Faces component libraries, then move the declarations to top of the
<h:body>
. This is not necessary for<o:criticalStylesheet>
nor<o:deferredScript>
as they already auto-relocate by themselves.<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.Since 3.11,
<h:outputStylesheet media="print">
will be explicitly excluded from the combined resource.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 Faces project stage is not set to
Development
as perFaces.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:
All available context parameters "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, jakarta.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 Faces project stage is not set to Development
as perFaces.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 referCache
javadoc."org.omnifaces.COMBINED_RESOURCE_HANDLER_CROSSORIGIN"
Set the desired value of crossorigin
attribute of combined script resources. Supported values are specified in MDN. Since 2.4, the default value isanonymous
(i.e. no cookies are transferred at all). Since 3.13, when the value isanonymous
, then the combined resource handler will also set theintegrity
attribute with a base64 encoded sha384 hash as SRI, see also MDN.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 arefilename.ext
,folder/filename.ext
,library:filename.ext
andlibrary: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 parameterorg.richfaces.resourceOptimization.enabled
set totrue
, 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.CDNResource
Since 2.7, if you have configured a custom
ResourceHandler
which automatically uploads the resources to a CDN host, including the combined resources, and you want to be able to have a fallback to local host URL when the CDN host is unreachable, then you can let your customResourceHandler
return aCDNResource
which wraps the original resource and the CDN URL. The combined resource handler will make sure that the appropriateonerror
attributes are added to the component resources which initiates the fallback resource in case the CDN request errors out.- Author:
- Bauke Scholtz, Stephan Rauh <www.beyondjava.net>
- See Also:
CombinedResource
,CombinedResourceInfo
,CombinedResourceInputStream
,DynamicResource
,DefaultResourceHandler
,InlineScriptRenderer
,InlineStylesheetRenderer
,InlineResourceRenderer
,CDNResource
-
-
Field Summary
Fields Modifier and Type Field Description static String
LIBRARY_NAME
The default library name of a combined resource.static String
PARAM_NAME_CACHE_TTL
The context parameter name to specify cache TTL of combined resources.static String
PARAM_NAME_CROSSORIGIN
The context parameter name to specify 'crossorigin' attribute of combined resources.static String
PARAM_NAME_DISABLED
The context parameter name to conditionally disable combined resource handler.static String
PARAM_NAME_EXCLUDED_RESOURCES
The context parameter name to specify resource identifiers which needs to be excluded from combining.static String
PARAM_NAME_INLINE_CSS
The context parameter name to enable rendering CSS inline instead of as resource link.static String
PARAM_NAME_INLINE_JS
The context parameter name to enable rendering JS inline instead of as resource link.static String
PARAM_NAME_SUPPRESSED_RESOURCES
The context parameter name to specify resource identifiers which needs to be suppressed and removed.-
Fields inherited from class org.omnifaces.resourcehandler.DefaultResourceHandler
FACES_SCRIPT_RESOURCE_NAME, RES_NOT_FOUND
-
Fields inherited from class jakarta.faces.application.ResourceHandler
JSF_SCRIPT_LIBRARY_NAME, JSF_SCRIPT_RESOURCE_NAME, LOCALE_PREFIX, RESOURCE_CONTRACT_XML, RESOURCE_EXCLUDES_DEFAULT_VALUE, RESOURCE_EXCLUDES_PARAM_NAME, RESOURCE_IDENTIFIER, WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME, WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME
-
-
Constructor Summary
Constructors Constructor Description CombinedResourceHandler(ResourceHandler wrapped)
Creates a new instance of this combined resource handler which wraps the given resource handler.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description Resource
createResourceFromLibrary(String resourceName, String contentType)
Returns a newCombinedResource
.String
getLibraryName()
ReturnsLIBRARY_NAME
.boolean
isListenerForSource(Object source)
Returns true if the source is an instance ofUIViewRoot
.void
processEvent(SystemEvent event)
Before rendering of a freshly created view, perform the following actions: Collect all component resources from the head.-
Methods inherited from class org.omnifaces.resourcehandler.DefaultResourceHandler
createResource, createResource, createResource, decorateResource, decorateResource
-
Methods inherited from class jakarta.faces.application.ResourceHandlerWrapper
createResourceFromId, createViewResource, getRendererTypeForResourceName, getViewResources, getViewResources, getWrapped, handleResourceRequest, isResourceRendered, isResourceRequest, isResourceURL, libraryExists, markResourceRendered
-
-
-
-
Field Detail
-
LIBRARY_NAME
public static final String LIBRARY_NAME
The default library name of a combined resource. Make sure that this is never used for other libraries.- See Also:
- Constant Field Values
-
PARAM_NAME_DISABLED
public static final String PARAM_NAME_DISABLED
The context parameter name to conditionally disable combined resource handler. @since 2.0- See Also:
- Constant Field Values
-
PARAM_NAME_EXCLUDED_RESOURCES
public static final String PARAM_NAME_EXCLUDED_RESOURCES
The context parameter name to specify resource identifiers which needs to be excluded from combining.- See Also:
- Constant Field Values
-
PARAM_NAME_SUPPRESSED_RESOURCES
public static final String PARAM_NAME_SUPPRESSED_RESOURCES
The context parameter name to specify resource identifiers which needs to be suppressed and removed.- See Also:
- Constant Field Values
-
PARAM_NAME_INLINE_CSS
public static final String PARAM_NAME_INLINE_CSS
The context parameter name to enable rendering CSS inline instead of as resource link.- See Also:
- Constant Field Values
-
PARAM_NAME_INLINE_JS
public static final String PARAM_NAME_INLINE_JS
The context parameter name to enable rendering JS inline instead of as resource link.- See Also:
- Constant Field Values
-
PARAM_NAME_CACHE_TTL
public static final String PARAM_NAME_CACHE_TTL
The context parameter name to specify cache TTL of combined resources. @since 2.1- See Also:
- Constant Field Values
-
PARAM_NAME_CROSSORIGIN
public static final String PARAM_NAME_CROSSORIGIN
The context parameter name to specify 'crossorigin' attribute of combined resources. @since 3.5- See Also:
- Constant Field Values
-
-
Constructor Detail
-
CombinedResourceHandler
public CombinedResourceHandler(ResourceHandler wrapped)
Creates a new instance of this combined resource handler which wraps the given resource handler. This will also register this resource handler as a pre render view event listener, so that it can do the job of removing the CSS/JS resources and adding combined ones.- Parameters:
wrapped
- The resource handler to be wrapped.
-
-
Method Detail
-
isListenerForSource
public boolean isListenerForSource(Object source)
Returns true if the source is an instance ofUIViewRoot
.- Specified by:
isListenerForSource
in interfaceSystemEventListener
-
processEvent
public void processEvent(SystemEvent event)
Before rendering of a freshly created view, perform the following actions:- Collect all component resources from the head.
- Check and collect the script and stylesheet resources separately and remove them from the head.
- If there are any resources in the collection of script and/or stylesheet resources, then create a component resource component pointing to the combined resource info and add it to the head at the location of the first resource.
- Specified by:
processEvent
in interfaceSystemEventListener
-
getLibraryName
public String getLibraryName()
ReturnsLIBRARY_NAME
.- Overrides:
getLibraryName
in classDefaultResourceHandler
- Returns:
- The library name on which this resource handler implementation should listen.
-
createResourceFromLibrary
public Resource createResourceFromLibrary(String resourceName, String contentType)
Returns a newCombinedResource
.- Overrides:
createResourceFromLibrary
in classDefaultResourceHandler
- Parameters:
resourceName
- The resource name.contentType
- The content type.- Returns:
- The library-specific resource.
-
-