egervari egervari - 4 months ago 17x
CSS Question

Unobtrusive way to combine and compress javascript/css for java/spring/maven applications?

I'd like to add some kind of library, or maven plugin, or 'something' to combine and compress my javascript and css source files.

However, I think this is pretty difficult to do unobtrusively with Java. The Rails people have pretty much solved this problem... it uses the unjoined/uncompressed files for development and then it compresses everything during production. It does this unobtrusively as you don't have to change your html headers or anything like that - it works for both testing and production. This is more or less what I want. Does it even exist in the Java space?

The last thing I want is to comment and uncomment lines of freemarker/html code for development and production - I want everything to be the same. Ideally, I'd want to be able to leave Tomcat running and code my javascript and css, and see my changes instantly - no delays or hickups. I also don't want to have to manually run a command to generate the new javascript every time I make a change... or even have some daemon constantly update it (because then it might not be instantaneous when I'm testing). At the same time, if I'm going to package up my war for production, I want it to use the joined and compressed files instead.

Is this even possible? If so, what tool should I be looking at? I know there are quite a few that do some of this, but they've fallen short on the "unobtrusive" aspect.



A solution that has worked for me is using the maven-minify-plugin (groupId is com.samaxes.maven) but only when building for production. Use a build property to specify if you are in development mode or not. Link to plugin

You can then have something like this (I don't know freemarker so I am just pasting some JSP code but I am sure it can easily be converted):

    <c:when test="${developmentMode}">
        <link rel="stylesheet" type="text/css" href="<c:url value="/css/custom1.css"/>"/>
        <link rel="stylesheet" type="text/css" href="<c:url value="/css/custom2.css"/>"/>
        <link rel="stylesheet" type="text/css" href="<c:url value="/css/another1.css"/>"/>
        <link rel="stylesheet" type="text/css" href="<c:url value="/css/another2.css"/>"/>
        <script type="text/javascript" src="<c:url value="/js/mylibrary.js"/>"></script>
        <script type="text/javascript" src="<c:url value="/js/more.js"/>"></script>
        <script type="text/javascript" src="<c:url value="/js/util.js"/>"></script>
        <script type="text/javascript" src="<c:url value="/js/whatever.js"/>"></script>
        <script type="text/javascript" src="<c:url value="/js/more.js"/>"></script>
        <link rel="stylesheet" type="text/css" href="<c:url value="/css/minified.css"/>"/>
        <script type="text/javascript" src="<c:url value="/js/minified.js"/>"></script>

This way non-minified/combined JS/css is used while in development and the minified css only used when building for production.

EDIT: As requested here is the code to expose Spring-defined beans on the ServletContext:

<bean class="">
    <property name="attributes">
            <!-- Obviously this can be changed to read from properties file -->
            <entry key="developmentMode" value="false" />