JavaScript: Rule 1

JavaScript development (for the web) is big right now, and in 2010 it’s only going to get bigger. There is a lot of information available on good practices for web application development with JavaScript, but if performance and maintainability matter to you, few things* are more important than Rule 1:

Source code is for humans, live code is for machines.

I first heard Christian Heilmann state this rule at @Media Ajax 2007 as “production code is for humans, live code is for machines” but I prefer the term “source code” to “production code”. The rule was important and prescient then; now I consider it the absolute foundation of any significant web application.

Development code is transformed into live code before being sent to the browser.

Rule 1 comes into play as soon as you have a project that involves any of the following:

  • More than a couple of hundred lines of JavaScript source code.
  • More than a couple of JavaScript source code files.
  • More than one developer.

In olden days (say, 2006), the JavaScript code for many web applications consisted of a single file. Comments were few and far between, and variable names were kept short because we wanted the code to be as small as possible. But this strategy does not scale. As projects get more complex, a single file filled with non-descriprive functions and one-letter variable names quickly becomes unreadable. In modern web application development there are two weapons we can use to tackle this problem: concatenation and minification.

Concatenation is the process of taking multiple JavaScript files, and combining them into a single file. Minification is the process of transforming a JavaScript source file to make it smaller. Early JavaScript minifiers just removed comments and unnecessary whitespace, but modern minifiers (YUI compressor, Dojo Shrinksafe, Google Closure Compiler) can also perform more aggresive optimizations, such as shortening variable names and removing unneeded code.

Basically, the JavaScript source code that developers write is no longer the JavaScript code that end users receive, and can see when they view the components for the page. The first benefit of this is performance: concatenating files reduces the number of HTTP requests web app requires, and minification reduces the download size (and can also reduce parsing time on the client). The second benefit comes in the form of better source code clarity, which is good for development and maintenance:

  • You can use multiple files to hold your source code, and organize them (naming convention, file hierarchy) however you want.
  • You can use lots of whitespace and comments throughout your source code.
  • You can use descriptive (long) variable and function names, because the minifier will try to reduce them to one-letter variables (identifier replacement).

A further consequence of this is that when you are writing JavaScript code, you now have to keep three audiences in mind:

  • The browser’s JavaScript interpreter. Your code MUST run in the target browser(s).
  • Humans. Your code SHOULD be clear and comprehensible to your colleagues.
  • The minifier (“compiler”). Your code SHOULD be structured to help your minifier apply its optimizations.

Personally, I am most familiar with the YUI compressor. If you choose to use it, then Nicholas Zakas’ slide deck on structuring your code for optimal optimization is required reading. In addition to helping the YUI compressor make your code even smaller, many of these tips make for tidier, more comprehensible code; and because they encourage the use of local instead of global variables, they can even make your code run faster too. Here are some of the main points:

  • Any literal value used two or more times should be stored in a local variable.
  • Any global variable used two or more times should be stored in a local variable.
  • Any property used two or more times should be stored in a local variable.
  • Try to use only one var keyword and one return statement per function.
  • Don’t use eval, with, or JScript conditional comments.

Where exactly you apply the concatenation and minification is up to you, and will depend on how your deployment pipeline is set up. You can do it as part of your build process, or you can do it at runtime — provided you have some form of caching enabled so that you don’t repeat the process for every request.

*Finally, I should note that the process of concatenation and minification is not the single most effective strategy in reducing the download size of your JavaScript components; that honour goes to gzipping, so I suppose that enabling gzip compression on your web application should, in the programming tradition of zero-based lists, be considered as “Rule 0”. But when it comes to maintaining a complex application, and delivering a compact download package, this is the way to go.