PDA

View Full Version : JsConcat - ant task for concatenating ExtJS projects



Niels Brouwers
31 Dec 2009, 4:48 AM
I am currently working on a rather large ExtJS project and I was looking at build systems for ExtJS. Specifically I want to concatenate all the js files and run it through some compressor/obfuscator.

Ant is a nice tool which I use for a lot of Java projects, and it works really well for ExtJS stuff too. I drive ext-doc with it, as well as yuicompressor, and concatenating or copying files for deployment is a snap.

The 'concat' task can concatenate files, but I didn't want to have to manually enter a file list as we have a large number of files, especially since we generally have a separate js file for each class. We can't just pass the task a list of all files in our source directory, because inclusion order matters (Ext.extends being the number one load-time dependency).

Therefore, I wrote an Ant task called 'JsConcat' that does some quick parsing to detect dependencies between js files based on @class and @extends comments, sorts the file list, and concatenates them. Example build file:



<!-- Define the 'jsconcat' task -->
<taskdef name="jsconcat" classname="com.zarafa.jsconcat.JsConcatTask">
<classpath path="JsConcat.jar"/>
</taskdef>

<!-- Concatinates JavaScript files with automatic dependency generation -->
<target name="concat">
<jsconcat
verbose="false"
destfile="${debugfile}"
prioritize="\w+, Foo.bar.*"
>
<fileset
dir="${sourcedir}"
includes="**/*.js"
/>
</jsconcat>
</target>


If you're familiar with Ant, it should be pretty clear what this does. If not, go have a look at Ant and read the manuals, it's pretty easy. Essentially, the source directory is scanned recursively and all js files are input into JsConcat.

There's three ways to influence the inclusion order. First, there are explicit dependencies that you can enter in your file:



/*
* This file needs to be included after bar.js
* #depends /foo/bar.js
*/


Then there's the dependencies that are extracted from @class and @extends:



/**
* Foo extends Bar, so the file in which Bar is defined should come before this file.
* @class Foo
* @extends Bar
*/


And finally, formatted as a comma-separated list of regular expressions, the prioritise argument can be used to move groups of files up the list. Files that have classes defined in them have those full class names matched against the regexps. Files that match the first priority group have the highest priority, files that match the second group come after that, and so on. We use this mainly to move the 'core' and 'common' packages to the top of the list.

For example,"\w+, Foo.bar.*" will move all files which have classes in the 'root' package (i.e. 'Date', 'Foo') to the top of the list, after wich come all files which have classes in 'Foo.bar' or any of its descending packages, and finally all the files that match neither of these criteria.

The regular expression format is the standard Java format (http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html).

I appended the source and a compiled version, plus an example build file that can serve as a template in case you want to try it out but don't have tons of Ant experience. The code is fairly simple, but if you have any questions, bugs, or want to make adjustments don't hesitate to ask.

Edit: new version, fixed a small bug cobaltblue came across. :">

hat27533
31 Dec 2009, 5:03 AM
Nice one, if you are using Java to build web apps there are a few others to consider too.

I run my js files through a js lint ant task at build time in netbeans using and the jslint4java (http://code.google.com/p/jslint4java/) ant task, this has saved me hours of debugging especial IE issues. I blogged about it here. (http://nnbs.blogspot.com/2009/09/enough-about-minifying-javascript-what.html)

There are also blog entires (http://nnbs.blogspot.com/2008/11/updated-minified-javascript-and-css.html) regarding minifying too, although I now tend to use JAWR (https://jawr.dev.java.net/) now.

jay@moduscreate.com
31 Dec 2009, 6:30 AM
Moved to Examples and extras

jay@moduscreate.com
31 Dec 2009, 8:06 AM
btw, thanks for the contribution :)

cobaltbluedw
21 Jan 2010, 2:11 PM
This tool looked quite handy, and I was going to use it, but when I try, I get a java.lang.NullPointerException.

target:


<target name="concat-dir">
<echo message="Concatinating all of '${srcFolder}' into '${destFile}'"/>
<jsconcat destfile="${destFile}" />
<fileset dir="${srcFolder}" excludes="${destFile}" includes="**\*.js" />
</jsconcat>
</target>


result:


concat-dir:
[echo] Concatinating all of 'C:\blah\blah\blah\scripts
' into 'C:\blah\blah\blah\scripts\pack.js.concat'

BUILD FAILED
C:\blah\blah\blah\build\catzip.xml:43: The following error occu
rred while executing this line:
C:\blah\blah\blah\build\catzip.xml:53: The following error occu
rred while executing this line:
C:\blah\blah\blah\build\catzip.xml:69: java.lang.NullPointerExc
eption


Any insight?

Niels Brouwers
25 Jan 2010, 3:22 AM
@cobaltblue: can you do a `ant -v` for me and paste the output? That way at I know in which line the thing fails, that way I know whether the problem is with the way the input from Ant is processed, or whether it's a problem with parsing the directives (i.e. @extends, etc).

Niels Brouwers
25 Jan 2010, 3:46 AM
@cobaltblue:

well this is embarrassing, turns out I forgot to initialise the 'prioritise' property to "" :"> I uploaded a fixed version, see original post.

cobaltbluedw
25 Jan 2010, 3:53 PM
Thanks a bunch Niels, I'll be sure to re-implement this when I get the chance! :D

liberborn2014
20 Jun 2014, 7:11 AM
Inspired by JsConcat and Combiner (https://github.com/nzakas/combiner) I have build another one tool to combine js projects. It uses native ExtJS "requires" parameters. So there is no need to handle dependencies in comments.

Extapp is the lightweight tool to build ExtJS applications. The main goal is to collect all dependencies required by JS application into one production-ready output file.
The tool is processing build in non-conflict manner. It may alert developer about errors and warnings but mainly it does not break the build because for example of duplicates or some class file was not found etc.
No additional comment conventions needed. Extapp avoids some custom magic comments like /*requires file.js */. It uses native ExtJS dependencies declarations in Ext.define() method or in any other place in the code.
The main features of the Extapp tool:

resolving dependencies
deduplicate referenced dependencies
ranking classes based on references
smart avoid of infinite loops
build sources into one output file
usage in other JS frameworks
More details: https://github.com/liberborn/extapp

mitchellsimoens
21 Jun 2014, 4:32 AM
Why not use Sencha Cmd now?

liberborn2014
23 Jun 2014, 12:28 AM
Sencha.cmd is the extraordinary tool to work with all Sencha products.


Extapp is about something different. It's light-weight stand-alone alternative of JS Compiler in Sencha cmd. It is flexible to include/exclude both native 'Ext' sources and other classes. It is working in non-conflict way and
deployment friendly.

That's much more easy to integrate 400Kb jar file into ant/gradle deployment scripts than install and setup Sencha software package. I was tired to set it up so I decided to write my own "bicycle".