NPM as an automated build system.

I hate having to set up complicated environments. I like JavaScript/Front End Development environments to be:

  1. Easy to understand and follow along for everyone on the team.
  2. Quick to get running and make changes.
  3. Free of having to learn new domain specific or pseudo languages for simple building.

Other platforms, Java or .NET, benefit from IDEs because they follow a predefined path and have a set of best practices defined into the language. The ugliness of JavaScript is why it’s powerful. But it can also lead to a lot of unnecessary reinventing the wheel.

Using NPM to use simpleton and replaceable tools keeps my projects fitting those three points above.

NPM is amazing and powerful. I’ve built three major projects now without Grunt or Gulp, using only NPM and locally installed modules.

The run command lets you run a locally installed module from the command line.

This runs “mocha test.js”

Scripts can also call one another.

In this previous example, “npm run check” will execute lint and test.

You can also use other NPM modules to run and watch the app.

For instance, in the following example, I use babel to convert and bundle the files after the lint and test. Then I run nodemon, which I have executing a custom script. Nodemon is also told to ignore the public directory where babel places the bundle. (I learned the fun way that this creates an infinite loop, if you don’t ignore it!)

"name": "npm as a build system example.",
"description": "This is a simple example of using npm as a build system.",
"repository": "n/a",
"license": "MIT",
"author": "Steven Lacks <> (",
"scripts": {
"build": "npm run lint && npm run test && npm run compile-js",
"compile-js": "babel src –out-file public/js/bundle.js –source-maps inline",
"lint": "eslint src",
"start": "http-server -p 3000",
"test": "mocha",
"auto-start": "nodemon –exec \"npm run build && npm start\" –ignore public/js"
"dependencies": {},
"devDependencies": {
"babel": "^5.8.21",
"eslint": "^1.1.0",
"http-server": "^0.8.0",
"mocha": "^2.2.5",
"nodemon": "^1.4.1"

view raw
hosted with ❤ by GitHub

// Example Project's File Structure
// src/
// public/
// js/
// css/
// …
// app.js
// package.js
// .eslintrc
// .gitignore

Now when I run “npm run auto-start” it won’t just run the lint and tests and launch the app, nodemon will also watch for changes, linting, testing and restarting each time a change is detected.

Building from NPM is incredibly powerful. When I need to change the files or directories, I can do it inside the string. If I want to change the linter, I can change the dependency, and the script for “lint’s” value. Run “npm install” to update the dependencies. Then all the existing “npm run lint” calls will call the new linter. There’s only a tiny amount of configuration and no coding, just a JSON file describing what I want to happen.

Multiple calls to the same NPM module are possible, while using a different command to have different options.

Finally, the best part about building with NPM way: All that someone on the team needs to do to include this automation or build this app on another machine is clone the files and run “npm install” to get it up and running (if they have Node installed).

When won’t automated building with NPM work? Well, sometimes I have more complex builds, where one area of code might use one set of tools and another area uses some other tools. Some operations are easier to do asynchronously, rather than through piping stdout. What I’ve found myself doing more, is using NPM for my smaller personal modules and I’m still using grunt for my large projects.

Thanks for reading, if you have any ideas, concerns, or complaints please let me know on twitter @StevenLacks or in the comments.

Written By StevenLacks