Use the servlet filter

This tutorial shows how you can setup WUIC with minimal configuration to filter any HTML page and serve the optimized result.

Prerequisites

You need to install first:

  • JDK 1.6

  • Maven 3

  • Servlet container (we advise to use an already tested server)

Purpose

We are going to setup the minimal configuration to process your statics on the fly. In this example, we consider the following statics to be processed at the root of your maven project:

.
|--src
   |--main
      |--webapp
         `index.html
         |--css
            `-- foo.css
         |--js
            `--foo.js

In our index.html file, we refer foo.css and foo.js as external resources using <script> and <link> elements.

Choosing the right dependencies

Define in your pom.xml a property 'wuic.version' with the latest release available on maven central We use SLF4J and WUIC comes with the API as dependency. Please refer to the documentation to import the logger you want.

First, import the servlet support for WUIC.

     <dependency>
         <groupId>com.github.wuic</groupId>
         <artifactId>wuic-servlet</artifactId>
         <version>${wuic.version}</version>
      </dependency>

In our example, we want to minify CSS, Javascript and HTML code. We can add the htmlcompressor and yuicompressor extensions for that:

    <dependency>
        <groupId>com.github.wuic.extensions</groupId>
        <artifactId>wuic-htmlcompressor</artifactId>
        <version>${wuic.version}</version>
    </dependency>

    <dependency>
        <groupId>com.github.wuic.extensions</groupId>
        <artifactId>wuic-yuicompressor</artifactId>
        <version>${wuic.version}</version>
    </dependency>

Configure your web.xml

WUIC is bootstrapped automatically thanks to a 'ContextListener` detected by the servlet container. However, you need to specify which resources you want to optimize (here the index.html file). This could be done by installing the WUIC servlet Filter:

    <filter>
        <filter-name>htmlParserFiler</filter-name>
        <filter-class>com.github.wuic.servlet.HtmlParserFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>htmlParserFiler</filter-name>
        <url-pattern>/index.html</url-pattern>
    </filter-mapping>

The optimized HTML will refer optimized CSS and Javascript scripts that need to be served at a specific location. To serve processed nuts in our servlet container, you need to declare the WUIC Servlet inside your web.xml file.

    <servlet>
        <description>WUIC servlet</description>
        <servlet-name>wuic</servlet-name>
        <servlet-class>com.github.wuic.servlet.WuicServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

Choose your servlet mapping for WUIC, for instance:

    <servlet-mapping>
        <servlet-name>wuic</servlet-name>
        <url-pattern>/wuic/*</url-pattern>
    </servlet-mapping>

That’s it

Open you browser display the index.html file. You will see that your HTML code is now minified. Open the referenced JS and CSS scripts, they are also minified!

Tip
According to the resource-hints specification, you will see in the HTTP response for the HTML page that one Link header for each external resources as been added. Thus the browser will be able to download those external resources without the need to fetch the HTML page before.
Tip
The first time your page is displayed, the server takes time before responding. This is because WUIC optimizes the page synchronously. After that, the result is added to a memory cache and future HTTP requests will be treated faster. We can take control over the cache implementation and add some configurations to display an already optimized page even the first time the page is loaded, but we will see it later.
Tip
If you reload the page, you will see that resources are loaded from the browser cache. WUIC has sent a far expiry header to the HTTP response in order to put resources in the browser cache. Don’t worry about cache busting, external resources URL contain a version number that WUIC updates when change are detected. We can also take control over version number computation, see details here.

JSP / Thymeleaf processing

We have seen how we can optimize a plain HTML page with the WUIC Filter. If you use a template processor, this tutorial shows how you can inject referenced resources optimized by WUIC in your page. Two sections describe how to do that for good old JSP users and for turned Thymeleaf users.

In our examples, we will consider two JS resources foo.js and bar.js and two CSS resources foo.css and bar.css. Those four files are stored in src/main/resources to be exposed in the root of the classpath at runtime.

Tip
in those tutorials the WUIC Filter could be use to optimize the generated HTML. However, you might not install it if you don’t see the value of just minifying the HTML code.

JSP tag

Use the maven dependency

You need to add the following dependency in your pom.xml to enable the JSP support:

      <dependency>
         <groupId>com.github.wuic</groupId>
         <artifactId>wuic-tag</artifactId>
         <version>${wuic.version}</version>
      </dependency>

Configure resource location in JSP

First we need to declare the resources to be injected. In your JSP, you can use the tag wuic-config to create a heap called statics that contains nuts corresponding to your statics.

    <%@ taglib prefix="wuic-conf" uri="http://www.github.com/wuic/xml-conf" %>
    <wuic-conf:xml-configuration>
        <wuic>
            <heaps>
                <heap id="statics">
                    <nut-path>js/foo.js</nut-path>
                    <nut-path>js/bar.js</nut-path>
                    <nut-path>css/foo.css</nut-path>
                    <nut-path>css/bar.css</nut-path>
                </heap>
            </heaps>
        </wuic>
    </wuic-conf:xml-configuration>
Tip
by default, WUIC retrieves resources relatively to the root of the classpath. We will see later how we can take control over the location of your resources.
Tip
we can configure resource location outside the JSP. This will be the topic of a subsequent tutorial.

Now we have to inject the <script> and <link> element where we want. Just use the wuic:html-import tag to inject the processed nuts in the page:

    <%@ taglib prefix="wuic" uri="http://www.github.com/wuic" %>
    <wuic:html-import workflowId="statics"/>

Thymeleaf processor

Use the maven dependency

You need to add the following dependency in your pom.xml to enable the thymeleaf support:

      <dependency>
         <groupId>com.github.wuic</groupId>
         <artifactId>wuic-thymeleaf</artifactId>
         <version>${wuic.version}</version>
      </dependency>

Use the dialect

Use the WUIC dialect:

  templateEngine.setDialect(new WuicDialect());

Create your template

First we need to declare the resources to be injected. In your template, you can use the tag wuic-config to create a heap called statics that contains nuts corresponding to your statics.

    <wuic:config>
        <wuic>
            <heaps>
                <heap id="statics">
                    <nut-path>js/foo.js</nut-path>
                    <nut-path>js/bar.js</nut-path>
                    <nut-path>css/foo.css</nut-path>
                    <nut-path>css/bar.css</nut-path>
                </heap>
            </heaps>
        </wuic>
    </wuic:config>
Tip
by default, WUIC retrieves resources relatively to the root of the classpath. We will see later how we can take control over the location of your resources.
Tip
we can configure resource location outside the template. This will be the topic of a subsequent tutorial.

Then in your head element, just use the attribute processor import to inject the processed nuts in the page:

<head wuic:import="statics">

That’s it

Now just run the application and load the page. Both JSP and Thymeleaf tutorials lead to the same result. You will see that one combined JS and one combined CSS have been imported!

Tip
we have configured WUIC with an XML structure supported by WUIC. You can find a deep description of all configurable elements via XML here. By the way, we will see progressively all the possibilities offered by the XML configuration step by step in the subsequent tutorials.

Custom DAOs

You can configure precisely how WUIC should access nuts by defining properties in custom DAOs. This tutorial shows how to change the base path in a classpath.

In the previous tutorials we used custom a JSP tag and Thymeleaf processor to configure WUIC. Here we will use a wuic.xml file which needs to be placed at the root of your classpath (src/main/resources).

Specifying custom DAOs

If default DAOs are not configured as you want, then you can declare a new configuration like this:

    <nut-dao-builders>
        <nut-dao-builder id="myDao">
            <properties>
                <property key="c.g.wuic.dao.basePath">/scripts</property>
            </properties>
        </nut-dao-builder>
    </nut-dao-builders>

Here we declare a DAO for classpath accesses which will retrieve any nut in /scripts. So, you may have something like that:

<?xml version="1.0"?>
<wuic>
    <nut-dao-builders>
        <nut-dao-builder>
            <properties>
                <property key="c.g.wuic.dao.basePath">/scripts</property>
            </properties>
        </nut-dao-builder>
    </nut-dao-builders>
    <heaps>
        <heap id="css">
            <nut-path>css/foo.css</nut-path>
        </heap>
        <heap id="js">
            <nut-path>js/foo.js</nut-path>
        </heap>
    </heaps>
</wuic>

This configuration manages two files in your classpath: /scripts/css/foo.css and /scripts/js/foo.js!

Tip
many components that you will discover through the documentation support equivalent properties. For instance, you can set the property c.g.wuic.basePath for both ClasspathNutDao (classpath access) and DiskNutDao (filesystem access). If you want to set the same value for a given property in all components, then you can drop a wuic.properties file in src/main/resources in order to locate it in the classpath root. In this property file, you can add all the properties and their value. For example, to specify the use of a wildcard * in the paths to resolve, write something like this:
# wuic.properties
# this property will be set for all components that support it
c.g.wuic.dao.wildcard=true
Tip
by default the DAO load resources from the classpath if you don’t specify the type attribute in the nut-dao-id-builder. Writing <nut-dao-builder> is equivalent to <nut-dao-builder type="ClasspathNutDaoBuilder">. You can find all the supported DAO with a deep description of this API here

Important notes

Caution
any nuts referenced by the declared nut should be accessible from its associated DAO. Common mistake is for instance to import an image in 'background' rule inside a CSS with a path not relative to the DAO’s base path associated to the CSS nut.

For instance, this configuration won’t work:

  • DAO with base path /css

  • Nut with path foo.css

  • An image referenced in foo.css with url('image/foo.png')

  • A structure like this:
    |_ css/foo.css
    |_ image/foo.png

Because the base path of the DAO associated to foo.js is /css, the image referenced in foo.css will be expected to be found at /css/image/foo.png.

Finally, it is better to define for instance a base path called '/statics' and to have a structure like this:
|_ statics/css/foo.css
|_ statics/image/foo.png

Caution
another reason to specify a particular base path is to make the file research faster. If you let the default base path, a large set of unnecessary files could be scanned.

Additional process

Behind each process operation, an engine is run. WUIC is fully modular and use engines provided out of the box. However, caching or compressing are some tasks you may want to delegate to external APIs like YUICompressor or EhCache. We will introduce how to do this with WUIC for those two APIs.

Specifying your engines

First of all, you have to put the right dependencies in your project. In this tutorial, we will replace the default cache implementation based on a memory Map by the EHCache support.

    <dependency>
        <groupId>com.github.wuic.extensions</groupId>
        <artifactId>wuic-ehcache</artifactId>
        <version>${wuic.version}</version>
    </dependency>

And that’s it! WUIC is able to auto-detect any extension added to the classpath and use it when processing nuts!

You’ll see in your logs that EhCache is now used to cache the results.

Configure your engines

With a little bit more of work, you can also configure the available properties of your engines.

The following configuration disables the cache:

<engine-builders>
    <engine-builder type="EhCacheEngineBuilder">
        <properties>
            <property key="c.g.wuic.engine.cache">false</property>
        </properties>
    </engine-builder>
</engine-builders>

Another solution is to add c.g.wuic.engine.cache=false in a wuic.properties file located in the classpath root. Note that with this approach the state will change for any component supporting the c.g.wuic.engine.cache property.

You will find all the available engines and the possible properties here.

Tip
for each engine, WUIC creates an instance used by default when some nuts are processed. The ID always match the naming convention wuicDefault[engine-builder-name]. For instance, the EHCache engine is called EhCacheEngine so the builder’s ID will be wuicDefaultEhCacheEngineBuilder. If the engine-builder-id attribute is not set in the engine-builder element, a default instance is used. So writing <engine-builder type="EhCacheEngineBuilder" engine-builder-id="wuicDefaultEhCacheEngineBuilder"> is equivalent to <engine-builder type="EhCacheEngineBuilder">.

Adding sprites

Applying sprites best practice

You can easily apply your sprites in css. However, combining your images takes time. This tutorial shows how WUIC helps developers to generate sprites.

Caution
WUIC can pack a set of PNG image only. Other format like JPEG will be just ignored by the ImageAggregatorEngine. Consequently if you want to include image in a format other than PNG you will need to convert them before.

The heap to gather your images

Declare all your images in a classic heap:

<heap id="img" dao-builder-id="imageDao">
    <nut-path>/foo.png</nut-path>
    <nut-path>/bar.png</nut-path>
</heap>

Import CSS sprites

If you have imported the underlying img workflow in your page, then you can assume that a CSS stylesheet with img_foo and img_bar classes are available so you can display each image by applying the associated class to any DOM element:

<span class="img_foo"></span>
...
<span class="img_bar"></span>

Find a sample here.

Using Javascript sprites

For developers using a HTML5 framework like SceneGraph, you can specify the generation of javascript sprites.

<engine-builders>
    <engine-builder id="wuicDefaultImageAggregatorEngineBuilder" type="ImageAggregatorEngineBuilder">
        <properties>
            <property key="c.g.wuic.engine.spriteProviderClassName">javascript</property>
        </properties>
    </engine-builder>
</engine-builders>

Where you finally import your img workflow, you can use in Javascript WUIC_SPRITE['img_foo'] and WUIC_SPRITE['img_bar'] to get an object with following properties:

  • x: x-position from the left inside the merged image

  • y: y-position from the top inside the merged image

  • w: the image width

  • y: the image height

  • url: the image URL

For SceneGraph users, you can use this factory and generate a CGSGNodeImage like this:

var imageFactory = new WUICCGSGNodeImageFactory("img");
var node = imageFactory.create('img_foo');
...

A sample can be found here.

Monitor changes

Feature

WUIC offers to users the possibility to load external resources (configurations and nuts). This tutorial shows how to enable a polling mechanism that detects any modification.

Polling wuic.xml

In your wuic.xml file, add the following attribute to root element:

<wuic polling-interval-seconds="10">
    ...
</wuic>

Every 10 seconds, WUIC checks if the file has been modified. If it is the case, then the configuration is reloaded without need redeploy your application or restart server.

To specify a different location of wuic.xml file, you can use following init-param in web.xml:

    <context-param>
        <param-name>c.g.w.wuicXmlPath</param-name>
        <param-value>file:/my_app/wuic.xml</param-value>
    </context-param>

Polling nuts

You can enable polling on a particular DAO like this:

<nut-dao-builder type="DiskNutDaoBuilder">
    <properties>
        <property key="c.g.wuic.dao.basePath">file:/my_app/statics</property>
        <property key="c.g.wuic.dao.pollingInterval">3600</property>
    </properties>
</nut-dao-builder>

Each hour, all nuts creates with the DAO will be polled. If any change is detected, then both browser and server caches are evicted to reload them.

Logging

Common loggers

WUIC uses slf4j as logging facade, which allows you to plug any supported logger behind the scene. All log levels are used by the library:

  • DEBUG logs are very verbose and should be activated only for debug purpose

  • INFO should be activated when you want to make sure that WUIC is active

  • WARN logs detect something you should not expect, while they don’t mean the static won’t be delivered to the client, hey should be always activated

  • ERROR logs mean that WUIC won’t deliver the statics successfully.

Special loggers

In addition WUIC provides special loggers using TRACE level:

  • com.github.wuic.Logging.TIMER will log all measured amount of time taken by process executions

  • com.github.wuic.Logging.POLLING will log all polling operations when you monitor nuts or configuration file

As an example, a configuration with spring-boot could be:

    logging.level.com.github.wuic.Logging.TIMER: TRACE
    logging.level.com.github.wuic.Logging.POLLING: TRACE

Process at build time

Purpose

Processing at build time could be a great solution for different use cases:

  • Statics are not served from your application server.

  • Application server can’t reach the server that serves statics to upload it.

  • You don’t use any Java application server but you use maven to package your application.

  • You don’t need to reload some configuration/statics at runtime and you want to reduce as much as possible the resources consumed at runtime by WUIC on your application server.

There are one benefit and one concern of build time solution:

  • Benefit: build time processing will turn to 0 the overhead induced by WUIC at runtime

  • Concern: no polling to reload both configuration and nuts at runtime

Configure your pom.xml

Options

Both task and maven plugin allow to configure the following options:

  • xml: the wuic.xml file location (which is configured as usual)

  • properties: the wuic.properties file location (which is optional)

  • output: base path where results are written by the plugin

  • charset: by default UTF-8, change it if you want to write processed text content (scripts, SVG, etc) with a different encoding

  • contextPath: the context path of the web server that will serve the generated statics (which is optional)

You will see in the next sections how they can be declared.

With Maven plugin

You can use the static-helper-maven-plugin that is commonly configured like that in the build section of your pom.xml:

<plugin>
    <groupId>com.github.wuic.plugins</groupId>
    <artifactId>static-helper-maven-plugin</artifactId>
    <version>${project.version}</version>
    <executions>
        <execution>
            <phase>generate-resources</phase>
            <goals>
                <goal>process</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <xml>src/main/resources/wuic.xml</xml>
        <properties>src/main/resources/wuic.properties</properties>
        <relocateTransformedXml>true</relocateTransformedXml>
        <output>${build.finalName}</output>
    </configuration>
</plugin>

The maven plugin has the following specific options:

  • relocateTransformedXml: when set to true, after statics have been processed, the plugin will move a transformed wuic.xml file to your out directory with some metadata files. This will allow the servlet to serve the process result from the application server by picking information from classpath.

With ANT integration

WUIC support ant integration. For instance, you can configure the maven-antrun-plugin like that:

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.8</version>
    <executions>
        <execution>
            <phase>prepare-package</phase>
            <configuration>
                <target name="wuic-target">
                    <property name="wuic-jar" value="${maven.dependency.com.github.wuic.wuic-core.jar.path}"/>
                    <property name="wuic-output" value="${project.build.directory}/${project.build.finalName}" />
                    <ant antfile="${basedir}/build.xml">
                        <target name="wuic-task"/>
                    </ant>
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>

In your build.xml file, just add:

<project>
    <target name="wuic-task">
        <taskdef name="wuic" classname="com.github.wuic.WuicTask" classpath="${wuic-jar}"/>
        <wuic xml="src/main/resources/wuic-ant.xml"
              properties="target/classes/wuic-ant.properties"
              relocateTransformedXmlTo="${wuic-output}/WEB-INF/classes"
              output="${wuic-output}"
        />
    </target>
</project>

The task has the following specific options:

  • relocateTransformedXmlTo: if defined, a location where the transformed wuic.xml file some metadata must be written. This directory should be added to your classpath at runtime to allow the servlet to serve the process result from the application server by picking information from classpath.

Configure

Configure for pure HTML pages

If your application just contains .html files, then you can filter them with WUIC and then directly serve them.

Configure your wuic.xml by adding just a heap that resolves the HTML pages:

<heap id="html" dao-builder-id="htmlClasspathNutDaoBuilder">
    <nut-path>.*.html</nut-path>
</heap>

Then, according to the output location, you will find the transformed HTML files. The extracted scripts are also copied. All files are stored under a directory named with the version number. This way you can deploy the directories in your application server to serve new paths not in the browser cache when content files change.

The website serves statics generated with a simple "mvn clean install" and is a good example or the approach. Check the source here.

Tip
if your statics are not served by the Servlet provided by WUIC, both cache and link headers won’t be set in the HTTP response for the HTML page. In that case, WUIC will modify the HTML to respectively insert a (cache manifest file and a link tag to the content.
Tip
if your statics are going to served by the Servlet container, the ContextListener will automatically install a Filter that optimize each resource by enabling the browser cache. It will also GZIP the content if the client supports it.

Configure for templating usage

If you use templating project like JSP or Thymeleaf, then you can build your application as usual and then use the maven plugin to create a file added to the classpath. At runtime, WUIC will read this file which refers statics generated at build time.

Examples

JSP

You have the sample here.

Also take a look at this sample, which performs optimizations at runtime but can be configured at build-time if you run mvn clean package -Pbuild-time.

Full static

wuic.github.io is processed by WUIC. You can check the sources in a branch here. The publish.sh script run WUIC and copy results in master branch.