10 Habits of a Happy Node Hacker

Listen to this article

This post is from 2014 - check out the update!

For most of the nearly twenty years since its inception, JavaScript lacked many of the niceties that made other programming languages like Python and Ruby so attractive: command-line interfaces, a REPL, a package manager, and an organized open-source community. Thanks in part to Node.js and npm, today's JavaScript landscape is dramatically improved. Web developers wield powerful new tools, and are limited only by their imagination.

What follows is a list of tips and techniques to keep you and your node apps happy.

npm includes an init command which walks you through the process of creating a package.json file. Even if you're intimately familiar with package.json and its properties, npm init is a convenient way to get your new node app or module started on the right track. It sets smart defaults for you, like inferring the module name from the parent directory name, reading your author info from ~/.npmrc , and using your git settings to determine repository .

mkdir my-node-app cd my-node-app npm init

It's good to get in the habit of using --save (or --save-dev ) every time you install a module that's local to your project. These flags add the given module to your package.json's dependencies (or devDependencies ) list and use a sensible default semver range.

npm install domready --save

Notice that npm now uses caret-style semver ranges:

"dependencies": { "domready": "^1.0.4" }

Setting a value for scripts.start in package.json allows you to start your app on the command line with npm start . This is a great convention to follow, as it allows any node developer to clone your app and get it running easily without any guesswork.

Bonus: If you define scripts.start in your package.json file, you don't need a Procfile. A Procfile will be created automatically using npm start as the web process.

Here's an example start script:

"scripts": { "start": "node index.js" }

Just as anyone on your team should be able to run your app, they should also be able to test it. The scripts.test field in package.json is used to specify the script to run your test suite. If you're using something like mocha to run tests, be sure to include it in devDependencies in package.json, and refer to the binary that's local to your project, rather than the mocha you have installed globally:

"scripts": { "test": "mocha" }

Many node apps use npm modules with C dependencies like bson , ws , and hiredis that must be compiled for Heroku's 64-bit Linux architecture. This compilation step can be a time-consuming process. To keep builds as fast as possible, Heroku's node buildpack caches dependencies after they're downloaded and compiled so they can be re-used on subsequent deploys. This cache means reduced network traffic and fewer compiles.

Ignoring the node_modules directory is also the npm recommended practice for module authors. One less distinction between apps and modules!

echo node_modules >> .gitignore

From the npm config docs:

Any environment variables that start with npm_config_ will be interpreted as a configuration parameter. For example, putting npm_config_foo=bar in your environment will set the foo configuration parameter to bar . Any environment configurations that are not given a value will be given the value of true. Config values are case-insensitive, so NPM_CONFIG_FOO=bar will work the same.

As of recently, app environment is available in all Heroku builds. This change gives node users on Heroku control over their npm configuration without having to make changes to application code. Habit #7 is a perfect example of this approach.

The public npm registry has seen immense growth in recent years, and with that has come occasional instability. As a result, many node users are seeking alternatives to the public registry, either for the sake of speed and stability in the development and build cycle, or as a means to host private node modules.

A number or alternative npm registries have popped up in recent months. Nodejitsu and Gemfury offer paid private registries, and there are some free alternatives such as Mozilla's read-only S3/CloudFront mirror and Maciej Małecki's European mirror.

Configuring your Heroku node app to use a custom registry is easy:

heroku config:set npm_config_registry=http://registry.npmjs.eu

If you've been programming long enough, you've probably been to dependency hell. Fortunately Node.js and npm have set a precedent for sane dependency management by embracing semver, the Semantic Versioning Specification. Under this scheme, version numbers and the way they change convey meaning about the underlying code and what has been modified from one version to the next.

npm has a little-known command called outdated . Combined with npm update , it's a great tool for figuring out which of your app's dependencies have fallen behind and need to be updated:

cd my-node-app npm outdated Package Current Wanted Latest Location ------- ------- ------ ------ -------- express 3.4.8 3.4.8 4.0.0-rc2 express jade 1.1.5 1.1.5 1.3.0 jade cors 2.1.1 2.1.1 2.2.0 cors jade 0.26.3 0.26.3 1.3.0 mocha > jade diff 1.0.7 1.0.7 1.0.8 mocha > diff glob 3.2.3 3.2.3 3.2.9 mocha > glob commander 2.0.0 2.0.0 2.1.0 mocha > commander

If you're working on open-source node apps or modules, check out david-dm, NodeICO, and shields.io, three great services that provide graphical badges you can use to display live dependency info on your project's README or website.

As the npm ecosystem continues to grow, so do the options for automating the development and build process. Grunt is by far the most popular build tool in the node world today, but new tools like gulp.js and plain old npm scripts are also attractive options with lighter footprints.

When you deploy a node app to Heroku, the npm install --production command is run to ensure your app's npm dependencies are downloaded and installed. But the command does something else too: It runs any npm script hooks that you've defined in your package.json file, such as preinstall and postinstall . Here's a sample:

{ "name": "my-node-app", "version": "1.2.3", "scripts": { "preinstall": "echo here it comes!", "postinstall": "echo there it goes!", "start": "node index.js", "test": "tap test/*.js" } }

These scripts can be inline bash commands or they can refer to command-line executables. You can also refer to other npm scripts from within a script:

{ "scripts": { "postinstall": "npm run build && npm run rejoice", "build": "grunt", "rejoice": "echo yay!", "start": "node index.js" } }

Harmony is the working name for ES6, the next edition of the ECMAScript language specification commonly known as JavaScript. Harmony brings lots of exciting new features to JavaScript, many of which are already available in newer versions of node.

Harmony enables many new features like block scoping, generators, proxies, weak maps, etc.

To enable harmony features in your node app, specify a newer node engine like 0.11.x and set the --harmony flag in your start script:

{ "scripts": { "start": "node --harmony index.js" }, "engines": { "node": "0.11.x" } }

Client-side JavaScript has a spaghetti-code legacy, but the language itself is not to blame. The lack of a legitimate dependency manager is what kept us in the jQuery-plugin copy-pasta dark ages for so many years. Thanks to npm, we're entering the front-end renaissance: the npm registry is growing like crazy, and the proliferation of modules designed to work in the browser is staggering.

Browserify is an amazing tool that makes node modules work in the browser. If you're a front-end developer, browserify could change your life. Maybe not today, and maybe not tomorrow, but soon. To get started using browserify, check out the articles.

Whether you've been developing in node for a while or are just getting started, we hope you find these tips useful. If you've got some (healthy) node habits to share, tweet about it with the #node_habits hashtag. Happy hacking!

By the way, we're hiring node people!