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.
1. Start new projects with npm init
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
2. Declare all dependencies
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"
}
3. Specify a start script
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"
}
4. Specify a test script
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"
}
5. Keep dependencies out of source control
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
6. Use environment variables to configure npm
From the npm config docs:
Any environment variables that start with
npm_config_
will be interpreted as a configuration parameter. For example, puttingnpm_config_foo=bar
in your environment will set thefoo
configuration parameter tobar
. Any environment configurations that are not given a value will be given the value of true. Config values are case-insensitive, soNPM_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.
7. Bring your own npm registry
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.
Configuring your Heroku node app to use a custom registry is easy:
heroku config:set npm_config_registry=http://registry.npmjs.eu
8. Keep track of outdated dependencies
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.
9. Use npm scripts to run custom build steps
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"
}
}
10. Try new things
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"
}
}
11. Browserify
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.
What are your habits?
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!