The choice of a build tool is usually based on the tools familiar to the developers who will be using it. My personal favorite tool for JavaScript build systems is Ant. Ant was originally created as a build tool for Java projects, but its easy XML syntax and built-in tasks make it an excellent choice for JavaScript as well. In an informal survey I conducted prior to writing this book, Ant was by far the most frequently cited build tool used for JavaScript, despite the recent introduction of newer build tools. If you find that Ant doesn’t quite work for you, several alternatives are listed in Appendix B.
This book focuses on JavaScript build systems using Ant, but all of the tools and techniques discussed can be applied to other build systems as well.
Ant requires Java to run, so make sure that you have Java installed on your system. If you’re using Mac OS X, then Ant is already installed by default; for Ubuntu, run sudo apt-get install ant to install Ant. For other operating systems, following the instructions at http://ant.apache.org/manual/install.html.
The main build file for Ant is build.xml. When Ant runs on the command line, it looks for this file in the current directory, so it’s best to place build.xml in the root directory of your project. You needn’t keep all of the build-related information in this file, but build.xml must be present for Ant to work.
As you might expect, build.xml is an XML file containing instructions on how to perform the build. There are three basic parts of an Ant build system:
A single step in the process such as running a program or copying a file
A named grouping of tasks into sequential order
A named container for all targets
Each part of the build system is represented by an XML element. Here’s a sample build.xml file:
<project name="maintainablejs" default="hello">
<target name="hello">
<echo>Hello world!</echo>
</target>
</project>Every build.xml file begins with a <project> element representing the overall project. The name attribute is required and uniquely
identifies this project. The default
attribute specifies the default target to execute if no target is
explicitly provided.
This file contains a single target, represented by the <target>
element. The name attribute is also
required here. The <echo> element
represents the echo task, which outputs the enclosed text to
the console. You can have any number of tasks in a target and any number
of targets in a project.
It’s a standard practice to define targets as atomically as possible so they can be combined in any number of ways. Think of targets like you would functions, as a logical grouping of repeated tasks.
Once you have a build.xml file, open a command prompt in that directory and type:
ant
By default, Ant will read the build.xml file
and default attribute of <project> to determine which target to execute. If you were to run
ant with the
build.xml file from the previous example, it would
execute the hello target. You can
optionally specify which target to run right on the command line:
ant hello
When the target name is specified on the command line, Ant no longer uses the default target.
In both cases, you’ll see console output that looks like this:
Buildfile: /home/nicholas/tmp/build.xml
hello:
[echo] Hello world!
BUILD SUCCESSFUL
Total time: 0 secondsThe output always shows you the build file being used as the first line. After that, you’ll see the target being executed followed by a list of tasks being executed. The task name is enclosed in square braces; any output is displayed to the right. You will also see a message in capital letters indicating whether the build was successful, followed by the amount of time the build took. These items are all helpful in determining the cause of build errors.
Each target may optionally be specified with dependencies—other targets that
must be run and must succeed before the current target is executed.
Dependencies are specified using the depends attribute, which is a comma-separated
ordered list of targets to execute first. Here’s an example:
<project name="maintainablejs" default="hello">
<target name="hello">
<echo>Hello world!</echo>
</target>
<target name="goodbye" depends="hello">
<echo>Goodbye!</echo>
</target>
</project>In this build.xml file, the target goodbye has a
dependency on the target hello. Thus,
running ant goodbye results in the following
output:
Buildfile: /home/nicholas/tmp/build.xml
hello:
[echo] Hello world!
goodbye:
[echo] Goodbye!
BUILD SUCCESSFUL
Total time: 0 secondsYou can tell from the output that the hello target was executed before the goodbye target, and that both succeeded.
In most build files, there are a small number of targets that you’ll use frequently. The majority of targets are single steps that are designed to be used by rollup targets that execute multiple targets in a specific order.
Ant properties are similar to variables in JavaScript, as they are generic
containers for data that can be changed and manipulated throughout
execution of the build script. A property is defined using the <property>
element:
<project name="maintainablejs">
<property name="version" value="0.1.0" />
</project>Each <property> element
requires name and value attributes. You can later reference the property by using ${version}, such as:
Version is ${version}When this Ant script is executed, the output is:
Buildfile: /home/nicholas/tmp/build.xml
version:
[echo] Version is 0.1.0
BUILD SUCCESSFUL
Total time: 0 secondsThe special ${} syntax is used
any time you want to insert a property value into task.
Properties can also be defined in a Java properties files and loaded directly into Ant. For instance, suppose you have a properties file named build.properties containing the following:
version = 0.1.0 copyright = Copyright 2012 Nicholas C. Zakas. All rights reserved.
You can import these properties into the Ant script by using
the <loadproperties> element and specifying
the filename with the srcfile
attribute:
<?xml version="1.0" encoding=UTF-8"?>
<project name="maintainablejs" default="version">
<property name="version" value="0.1.0" />
<target name="version">
<echo>Version is ${version}</echo>
</target>
</project>Properties loaded using <loadproperties> are accessible in the
same manner as those defined explicitly within
build.xml. For a large number of properties, or
properties that need to be shared among multiple Ant scripts, it’s best to
have them in a separate Java properties file.
At a minimum, it’s best to have several properties declared that can be used throughout your project, such as:
src.dirThe root source code location
build.dirWhere the built files should end up
lib.dirLocation of dependencies
Throughout the rest of this book, you’ll see these properties used in Ant tasks. Be sure to define them appropriately in your project.
Buildr (https://github.com/nzakas/buildr) is a project that seeks to collect common frontend-related Ant tasks with easier syntax. A wide range of tools is available for working with JavaScript files, but they all work a bit differently. Buildr wraps all of these different tools in tasks that can be used in your Ant scripts.
To use Buildr, you must first get a copy of the source. Once you have the directory structure on your computer, you can import all of the tasks with this command:
<import file="/path/to/buildr/buildr.xml"/>
This command allows your build.xml file to make use of all the custom tasks defined in Buildr. The following chapters show you both how to create Ant tasks from scratch as well as how to use the Buildr tasks.