I\'m interested in hearing how you prefer to automate Javascript minification for your Java web apps. Here are a few aspects I\'m particularly interested in:
I tried two ways:
Of course the latter solution is better since it does not consume resources at runtime (my webapp is using google app engine) and it doesn't complicate your application code. So assume this latter case in the following answers:
How does it integrate? Is it part of your build tool, a servlet filter, a standalone program post-processing the WAR file, or something else?
using maven
Is it easy to enable and disable? It's very unfunny to try and debug a minified script, but it's also useful for a developer to be able to test that the minification doesn't break anything.
you activate it only when assemblying the final war; in development mode you see the uncompressed version of your resources
Does it work transparently, or does it have any side effects (apart from the ones inherent in minification) that I have to consider in my day-to-day work?
absolutely
Which minifier does it use?
YUI compressor
Does it lack any features that you can think of?
no, it is very complete and easy to use
What do you like about it?
it is integrated with my favourite tool (maven) and the plugin is in the central repository (a good maven citizen)
Our project has handled it a number of ways but we have continued to use the YUI Compressor through our different iterations.
We initially had a servlet handle the compression for JavaScript the first time that particular file was accessed; it was then cached. We already had a system in place to handle custom property files so we simply updated our configuration files to support enabling or disabling the compressor depending on the environment we were working in.
Now the development environments never use compressed JavaScript for debugging purposes. Instead we handle the compression in our build process when exporting our application to a WAR file.
Our client has never raised concerns about the compression and the developers don't notice it until they decide to debug JavaScript. So I'd say it's rather transparent with minimal, if any, side affects.
Really late to the party here, but figured this might help someone still looking for a different answer:
After trying to use YUI Compressor, I was disappointed that it was incompatible with more recent versions of jQuery and Prism (the two main 3rd party JS libraries I needed for my project which I wanted compressed into a single file). So I decided to use Terser, which is a fork of Uglify-JS that supports ES6+. I wasn't able to get it to run directly using the <exec>
task, but using the Windows command line method works for Win 10, at least (not saying it can't work otherwise, but this was a very easy work-around). No need to add anything else to the Path system variable (as Node.JS is typically added during installation). I first use the ANT <concat>
task to make a big, uncompressed file. Use <fileset>
as it will preserve the order (if that's important, anyway).
<concat destfile="${js-big-file}" encoding="UTF-8" outputencoding="UTF-8" fixlastline="true">
<filelist refid="js-input-filelist"/>
</concat>
Then use the <exec>
task to run any NPM program, such as Terser. The Apache manual page on this task indicated this is the Windows workaround for running .bat files, but it really allows you run just about any command line application (even those that <exec>
mysteriously cannot find otherwise).
<exec executable="cmd">
<arg value="/c"/>
<arg value="terser"/>
<arg value="${js-big-file}" />
<arg value="-o" />
<arg value="${smaller-js-file}"/>
</exec>
Integrate? It is part of an ANT build script (a DITA Open Toolkit plugin to support custom JavaScript, among other things - not a Java Web application, per se, but using Java to build HTML5 output), so integration was not much more than adding those tasks to a new target (there's more code regarding setting defaults and checking input parameters!).
Easy to Enable/Disable? In my case, I have a parameter I pass to the ANT Build in order to include building and minifying the JS file. So yes, it only performs this target if I set the param to 'Yes'. That's a pretty easy thing to set up in an ANT build.
Transparent So far, it appears to have no effect on any of the several JS files I'm including. Some of those are my own (and I'm no JS expert, by any means) and some are, as I mentioned, common JS libraries.
Minifier Terser, but you could use just about any minified with command line input with this method.
Lack features? Terser only works with JavaScript. If I want to do the same for my CSS files (which I do), I use YUI Compressor.
Like That it is a currently active project and has good support. Plus, the current implementation (only calling it via the ANT <exec>
target) allows me to swap out minifiers should I need to use something else down the road.
Don't like That it requires Node.JS. Nothing against Node.JS, mind you, just that this particular project doesn't need it otherwise. I'd much prefer to use a Java .jar file like YUI Compressor for this (I can easily distribute that with a plugin should I need to).
We are using Ant task to minify js files with YUICompressor during production build and put result into a separated folder. Then we upload those files to a web server. You can find some good examples for YUI+Ant integration in this blog.
Here is an example:
<target name="js.minify" depends="js.preprocess">
<apply executable="java" parallel="false">
<fileset dir="." includes="foo.js, bar.js"/>
<arg line="-jar"/>
<arg path="yuicompressor.jar"/>
<srcfile/>
<arg line="-o"/>
<mapper type="glob" from="*.js" to="*-min.js"/>
<targetfile/>
</apply>
</target>
I think you need a compression library, for example Granule tag.
http://code.google.com/p/granule/
It gzip and combine javascripts wrapped by g:compress tag using different methods, also has Ant task as well
code sample is:
<g:compress> <script type="text/javascript" src="common.js"/> <script type="text/javascript" src="closure/goog/base.js"/> <script> goog.require('goog.dom'); goog.require('goog.date'); goog.require('goog.ui.DatePicker'); </script> <script type="text/javascript"> var dp = new goog.ui.DatePicker(); dp.render(document.getElementById('datepicker')); </script> </g:compress> ...
I'm writing a framework for managing web assets, called humpty. It aims to be simpler and more modern than jawr or wro4j by using WebJars and ServiceLoaders.
How does it integrate? Is it part of your build tool, a servlet filter, a standalone program post-processing the WAR file, or something else?
In development, a servlet processes the assets as necessary. The assets would then be pre-compiled before production and placed in a public folder, so that the only part that is used is generating the correct includes in the HTML.
Is it easy to enable and disable? It's very unfunny to try and debug a minified script, but it's also useful for a developer to be able to test that the minification doesn't break anything.
That would be done by switching between development and production modes.
Does it work transparently, or does it have any side effects (apart from the ones inherent in minification) that I have to consider in my day-to-day work?
I believe it is transparent, but does strongly favour the use of WebJars.
Which minifier does it use?
Whichever one the plugin you put on your classpath uses. Currently looking at writing a plugin for the Google Closure Compiler.
Does it lack any features that you can think of?
Still pre-release, though I'm using it in production. The maven plugin still needs a lot of work.
What do you like about it?
The simplicity of just adding a dependency to configure the framework
What don't you like about it?
It's my baby, I love it all ;)