Common

What is the version of the JDK to use?

WUIC library is currently compiled with the JDK v1.6u45!

Is it a replacement for Node.JS?

Yes and no.

For non-java developer: No. Node.JS is awesome and provides, through npm, a lot of assets processors like grunt or gulp. When you develop your app with Node.JS, you have the set of great tools that help you manage your web assets efficiently.

For java developers: Yes. When you write a web application with Java, you can start to find a lot of boilerplate based on very different solutions in your stack if you mix it with Node.JS. Java ecosystem already offers a lot of frameworks and tool like maven or spring that should be extended to process web assets through their API already used for other purposes.

Finally, it is not necessarily mandatory to chose between a WUIC and a Node.JS based solution. WUIC also tries to provide a better integration of any kind of tool in Java application thanks to an unified API. In other words, the goal of the project is to make easier Node.JS integration for Java developer.

Is it a replacement for Spring Resource Handling?

No.

Spring Resource Handling is extensible by design. WUIC can be plugged into the Spring WEB architecture with a dedicated extension.

Who are our competitors?

Projects like WRO4J, JAWR or Granule address similar issues in a similar scope than WUIC. Those projects have different priorities, and a state that differ to each other. You won’t find any competitive benchmark in our site, as we consider them as the institutionalization of cheating. If we don’t convince you, we prefer you to make your own opinion by testing several solution, or by getting feedback from the community ;-)

Does HTTP/2 makes tools like WUIC obsolete?

No.

Some optimizations should be indeed removed:

  • Domain sharding: with HTTP/2, several requests can be submitted to the same domain in parallel

  • Cookie free domains: multiplexing avoid the overhead linked to cookies sent with each request

Other optimization should be kept with cautions:

  • Aggregation, inlining and sprites: make sure that all resources are used in the page. Otherwise prefer taking advantage from multiplexing.

Finally, several optimizations are still recommended:

  • Minimize Javascript, CSS and HTML

  • Remove redundant data from image

  • Enable browser cache

  • GZIP the content

  • Resource hint

And don’t forget server-push from HTTP/2 protocol that could be enabled easily with tools like WUIC.

What about performances?

Because of the capability to process statics on the fly, you have to know some performance considerations.

Each time a static is required from the page, the request goes through WUIC’s servlet and is parsed by the library. What does WUIC is quite simple and is executed very quickly, so there is no particular performance doubts to have about the use of WUIC.

What is important is the cache strategy you want to choose to not redo the same job each time the same static is requested. In fact, some tasks like image aggregation are very time consuming. WUIC provides caching support like EhCache. However, you can perfectly cache the resources generated by WUIC in a reverse proxy like Varnish. So the first time a static is requested, the user will wait for the end of the job before getting it. You can improve it if necessary with the best effort mode.

Finally, in addition to the cache enabled on server side, WUIC provides a nice browser cache mechanism that will improve your response time.

What JEE server can I use?

WUIC is designed to be used on any kind of servlet container. However, not all of them have been tested. You can follow the state of the tests here.

Moreover, you have to know that you can process your statics at build time and serve them on any HTTP server. This way, using a servlet container is optional if you don’t want to use tag helpers (JSP, Thymeleaf, etc).

Advanced

I turn on the regex option in my wuic.xml and no nuts match my regular expression

First of all, your regex will always be compiled by the Pattern class in the JAVA API.

However, the JAVA API won’t be always used to check if a nut matches or not. In fact, the regular expression support is deeply related to the protocol used by WUIC to access the resources.

  • SSH: depends on the command software used on the remote server. If it is /bin/sh, then refer to find command. If it is cmd.exe, refer to dir command. No other command is currently supported.

  • HTTP: not supported. Applying a research based on a regular expression is tricky and maybe not possible.

  • Others: the Matcher in Java API will be used. Just keep in mind that test excludes the base path you configured for the DAO. For example, if your base path is /foo/bar, two files /foo/image.png and /foo/bar/wuic/image.png exist and your pattern is .wuic.png, then only /foo/bar/wuic.png will match because /foo/image.png is outside the base path.

Polling feature not always works when nuts are embedded in the webapp

Two different supports of webapp accesses are provided by WUIC: one for exploded war deployment and one for packaged deployment.

WUIC detects transparently when the war file is exploded by the server. In this case, it uses a mechanism which supports polling so update could be detected easily. However, if you deploy a packaged war without exploding it, the ServletContext does not provide real path on the file system so WUIC is not able to find it and to check the last modification date.

Take care of how you deploy your application. We encourage to use polling feature for webapp resources only for cache invalidation during development. In this context, you can use exploded mode on your local server. However, when your to production, you may deploy the packaged war without exploding it to prevent manual modifications and to guarantee the running version. This consideration does not suit the polling philosophy which considers hot redeployment. In that case, you may prefer to perform polling operations on files outside the webapp.

How can I show the logs of WUIC?

WUIC uses SLF4J as logging facade. You can refer to the SLF4J documentation to see how configure logs. Usually, if your log level filter strategy is based on package, keep in mind that all classes of WUIC are under the com.github.wuic package.

Why so many logs are generated from JavascriptYuiCompressorErrorReporter?

This class is an implementation of an ErrorReporter from YUICompressor to see every issues detected by YUICompressor when it processes Javascript files. It often detects a lot of warnings and, if you are ok with that, you may want to disable those logs. For instance, in Log4J:

<logger name="JavascriptYuiCompressorErrorReporter">
    <level value="OFF" />
</logger>

WUIC fails when I use JRebel

On startup, WUIC checks the base path for its DAO. By default, disk based DAO will look for the root of your webapp. If you define a target in your rebel.xml that points to the root context path, the servlet context will return a bad location.

Common mistake in rebel.xml:

<application>
    <web>
        <link target="/">
            <dir name="/my-project/web/src/main/webapp"></dir>
        </link>
        <link target="/">
            <dir name="/my-project/web/overlays/other"></dir>
        </link>
    </web>
</application>

Better:

<application>
    <web>
        <link target="/">
            <dir name="/my-project/web/src/main/webapp"></dir>
        </link>
        <link target="/other">
            <dir name="/my-project/web/overlays/other"></dir>
        </link>
    </web>
</application>

Content sent from WUIC servlet and/or filter is not well encoded

WUIC uses the file.encoding JVM property value when setting charset. Just specify the character encoding you want WUIC use to the JVM parameters. For instance, if you use UTF8, you may add this:

-Dfile.encoding=UTF-8

Got NoClassDefFoundError or NoClassDefFoundException when I use WUIC

The problem is certainly related to your dependency management. You can take a look at our design decisions. Keep in mind that:

  • You need to explicitly declare the dependencies to EHCache and YUICompressor if you want to use the engines based on those projects.

  • Some protocol supports like FTP and SSH have a dedicated module in WUIC that you need to add to your pom.xml

Can nuts processed by WUIC have the same name?

We strongly discourage it.

In fact, we don’t guarantee two nuts with the same name won’t create an issue, even if they are referenced by different heaps. There’s many cases where names could be in conflict:

  • happens when you have a nut named foo.js and another nut foo.js referenced with the ../ notation (so you have something like ../../foo.js).

  • happens when you use sprites because CSS class or Javascript property are formatted and simplified (/bar/foo1.js and /foo/foo2.js gives foo_).

  • …​

My nuts referenced in CSS with @import or background-url are not processed by WUIC

First of all, WUIC won’t process absolute paths because we consider they are not in the same heap as the CSS which is referencing it. By extension, the key point for relative URL is to know if the path will be reachable by WUIC. To build the nut with the relative path, WUIC will use the NutDao used to build the nut referencing it.

Imagine you have a CSS 'foo/bar.css' declared in a heap associated to a NutDao configured with the base path /var/www/statics. To reach bar.css, WUIC will consider the absolute file path /var/www/statics/foo/bar.css. Now, if an image img/ref.png is referenced by bar.css, WUIC will consider the absolute path relatively to to bar.css file so it will check /var/www/statics/foo/img/ref.png file path.

If the computed path does not exists, then WUIC will just log the warning and won’t build the nut.

How my CSS classes names are generated when sprites are computed?

Naming convention is the same for both CSS and Javascript sprite usage.

In CSS, a class is created while in Javascript, a new property is added to the global constant "WUIC_SPRITE". Both names corresponds to the concatenation of the heap ID (and not workflow ID), an underscore and the nut name. For the nut name, the extension and the parent path are previously removed. Because the allowed name are very constrained for CSS class names and javascript properties, WUIC always replaces any non letter character by an underscore.

For instance, nut foo/bar/baz/My Image.png in heap My Sprite will result in a CSS class/javascript property named My_Sprite_My_Image.

My browser cache is evicted when I redeploy event if I don’t modify my sources

Several build tools like maven copy the sources to package you webapp and, according to your environment, the last modification timestamp is updated. Since WUIC uses this timestamp to compute an MD5 signature and adds it to the URL of any nut, client cache will be evicted when you deploy a new version of your application. You can configure your DAO to compute the MD5 by digesting file content. This way, the URL won’t change when you redeploy your application if the content didn’t changed.

   <nut-dao-builder id="myDao" class="FtpNutDaoBuilder">
       <property key="c.g.wuic.dao.contentBasedVersionNumber">true</property>
   </nut-dao-builder>

Of course, the drawback is that this operation is slower because the whole content will be read, which increases startup time.

At build time, how to keep the filtered index.html inside the root directory?

The maven plugin always generate the files in a subdirectory named with its corresponding hash to evict browser cache when you deploy your statics. However, the filtered index.html is still served at the root of your server so by default you need to copy it manually, which could be done automatically with maven:

<plugin>
    <groupId>org.codehaus.gmaven</groupId>
    <artifactId>gmaven-plugin</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.ant</groupId>
            <artifactId>ant</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <id>copy-index</id>
            <phase>package</phase>
            <goals>
                <goal>execute</goal>
            </goals>
            <configuration>
                <source>
                    import groovy.io.FileType;
                    new File(pom.basedir, 'target/').eachFileRecurse(FileType.FILES) {
                        if (it.name.equals('index.html')) {
                            new File(pom.basedir, 'target/index.html').text = it.text;
                        }
                    }
                </source>
            </configuration>
        </execution>
    </executions>
</plugin>

At build time how the maven plugin can read filtered sources?

If you have some sources like javascript files filtered with maven, you need to configure your pom.xml properly to tell the WUIC plugin to read generated sources.

In your wuic.xml file, consider the base directory where files are generated:

    <nut-dao-builders>
        <nut-dao-builder type="DiskNutDaoBuilder">
            <properties>
                <property key="c.g.wuic.dao.basePath">target</property>
            </properties>
        </nut-dao-builder>
    </nut-dao-builders>

Then, just copy the resources to the target directory and tell the plugin to generated result into target/install directory.

<build>
    <plugins>
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.6</version>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${basedir}/target/${project.build.finalName}/install</outputDirectory>
                        <resources>
                            <resource>
                                <directory>${basedir}/src/main</directory>
                                <excludes>
                                    <exclude>path-of-filtered-sources</exclude>
                                </excludes>
                                <filtering>false</filtering>
                            </resource>
                            <resource>
                                <directory>${basedir}/src/main</directory>
                                <includes>
                                    <include>path-of-filtered-sources</include>
                                </includes>
                                <filtering>true</filtering>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>com.github.wuic.plugins</groupId>
            <artifactId>static-helper-maven-plugin</artifactId>
            <version>${wuic-version}</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>process</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <xml>src/main/resources/wuic.xml</xml>
                <output>target/install</output>
                <contextPath>webapp-path</contextPath>
            </configuration>
        </plugin>
    </plugins>
<build>

Contribute

WUIC is great, how to follow the project?

We also have a forum.

How can I contribute by using WUIC?

Please check our last release. Any feedback is welcome. You can use the a forum or the issue tracker on github.

How can I contribute by coding?

We use the nice pull request feature from github. Please contribute by creating PR on the most recent snapshot-x.x.x branch of our repositories.