JavaScript is a piece of cake, right? Step 1: Write it. Step 2: It runs on the client. What else is there to do?
Well, a couple of things. The first huge time saver is to run your code through JSLint. JSLint reports all kinds of bad practices that are worth considering, but even more helpful, it reports syntax errors that you won’t notice until you try to run your code in a browser. Getting these types of errors reported immediately saves a lot of time.
Next, it’s a good idea to merge as many JavaScript files as possible into one (same with CSS). When writing the code it is often handy to have lots of small files (one per widget for example), but that adds overhead when a user visits your page and their browser has to make a bunch of separate requests.
The last thing you probably want to do is minify your code. Removing all the whitespace, using shorter local variable names, etc. can shrink your file sizes by more than half, but also make them completely unreadable. So for the best of both worlds, write clean nicely formatted code (and save it in your repository) but then run it through a minification tool before using it on your site. There are several available, but we settled on the YUI Compressor because it is easy to use, cross-platform (written in Java) and also can compress CSS files.
But now this sounds like a lot of steps, right? So allow me to introduce… the Azavea Minifier! This is a python script that reads a simple config file and then performs all three steps for you, for easy use in your build process.
Here’s an example (all example files are included in the Minifier zip file):
Let’s say you have the following tree of input files:
src/ui.js (12kb)
src/images/banner-rtn.jpg
src/images/commonspace-banner.jpg
src/images/banner-ph.jpg
src/css/typography.css (10kb)
src/css/view.css (0.6kb)
src/css/style.css (30kb)
src/css/images/azavea-logo.png
src/css/images/azavea-homepage-hunchlab-banner.jpg
src/crypticfilenames/sfga.js (9kb)
src/crypticfilenames/ccm.js (2kb)
src/crypticfilenames/css/ccm.css (1kb)
src/crypticfilenames/css/images/banner-walkshed.jpg
All nicely arranged for development, but not so handy for deployment. So let’s minify it. First, create a config file.
The default config file name is “minifier.conf”, though you can specify a different file on the command line if you wish. The format consists of sections of files to be merged, with a header that is the new output file, like this:
[output/output.js]
input/input1.js
input/input2.js
[output/output.css]
input/input1.css
You can also use the minifier to simply copy files to an output directory, which can be useful when you have some random images or whatever that aren’t used directly by the CSS.
[output/outputdir]
input/somefiletocopy.txt
input/someotherfile.jpg
In our case, we have JavaScript code and CSS and related images scattered around our source tree, so our config looks like this:
[output/cryptic.js]
src/crypticfilenames/ccm.js
src/crypticfilenames/sfga.js
[output/main.js]
src/ui.js
[output/all.css]
src/css/style.css
src/css/typography.css
src/css/view.css
src/crypticfilenames/css/ccm.css
[output/images]
src/images/banner-ph.jpg
src/images/banner-rtn.jpg
src/images/commonspace-banner.jpg
Except there’s one problem: ui.js is chock full of JSLint errors, and I just downloaded it from somewhere and don’t intend to rewrite it. So let’s tweak that section so it won’t get JSLint run against it:
[output/main.js] --nolint
src/ui.js
Now run minifier.py, and your output should look like this:
output/all.css (43kb)
output/all-min.css (33kb)
output/cryptic.js (12kb)
output/cryptic-min.js (6kb)
output/main.js (12kb)
output/main-min.js (6kb)
output/images/azavea-homepage-hunchlab-banner.jpg
output/images/azavea-logo.png
output/images/banner-ph.jpg
output/images/banner-rtn.jp
output/images/banner-walkshed.jpg
output/images/commonspace-banner.jpg
Note that the minifier was kind enough to relocate any images it found referenced in the CSS files to the same location relative to the new CSS file (CSS paths are relative to the CSS file, not the page). Images it can’t find will generate a warning like this:
warning : Minifier can't find the file for this url referenced in the CSS: /foo/images/bullet-sm-gray.png
I left a few errors in the example JS so you can see the JSLint output as well. Currently it is formatted like this:
/foo/example/src/crypticfilenames/ccm.js: error JsLint : 28
line 18 character 28: Expected '===' and instead saw '=='.
if (ccm_siteActivated == false) {
(Which happens to be the format that Visual Studio will detect and display nicely in its error window.)
Note that in the output there are two versions of each output file:
file.ext
file-min.ext
The first one is what’s produced by merging, but not minifying, your files. This allows you to switch back and forth easily between the non-minified version when you need to debug (because minified files are pretty unreadable) and the minified version for production. The merged file has comments inserted indicating where each source file starts and ends, so after you find the bug you can easily fix it in the original file.
I hope you find this helpful! Feel free to offer any suggestions or bug reports.





1 Trackback
[...] This post was mentioned on Twitter by Reed Lauber and PhillyJS. PhillyJS said: RT @azavea: New Azavea Labs article: What's your JavaScript build process? http://bit.ly/fI79mI [...]