Most Node.js developers use npm as a package manager. However, npm is also a powerful task runner that can serve as a replacement for gulp. The `npm run` command lets you define custom scripts in your
package.json, so you can reduce complex node-related shell scripts into simple one-liners. In this article, you’ll learn about common
npm run use cases, including using
npm run to pipe ES6 browser code through Babel and Browserify.
Setting Environment Variables and Flags
Node.js has several handy configuration options you can set using environment variables and command line flags (like the old
--harmony flag that you used to enable ES2015 features in 0.12.x). The
npm run command, and
npm start in particular, let you set any flags your application needs before running.
For instance, the
NODE_PATH environment variable lets you add additional directories to the
require() function’s module search path. In other words, suppose your project has a
lib directory that contains your source code, and a
test directory that contains your tests. Let’s say you have a test in
test/e2e/my_feature/my_feature.test.js that wants to
require() in a function that’s declared in
lib/server/my_feature/utils.js. That’s going to involve a brittle
require('../../../lib/server/my_feature_utils'); command that’ll break every time your directory structure changes. However, if you run
env NODE_PATH=./ node test/e2e/my_feature/my_feature.test.js, require() will know to look in the current directory, so you can instead use:
Unfortunately, every environment variable and flag you need to set adds extra complexity to starting your application. Odds are, if you need to set 17 environment variables and flags to start your application, you’re going to forget one or two. Suppose your application relies on the
env NODE_PATH=./ trick as well as ES2015 proxies, which are hidden behind the
--harmony_proxies flag as of this writing. You can define a
start script in your package.json file as shown below.
Now, if you run
npm start (which is just short for
npm run start), npm will run the
start script for you and start your application with your special configuration options.
Command Line Shortcuts
Let’s face it, asking users to
npm install -g (usually) sucks. You may have heard that the upcoming gulp 4.0 release will be entirely incompatible with gulp 3.x. Since many people install gulp globally and there’s no way for
package.json to enforce globally-installed packages, a lot of users are going to end up playing a guessing game as to which version of gulp they need.
It’s much better to list gulp as a
package.json, but then you have to run
./node_modules/.bin/gulp watch rather than gulp watch, which is a pain. That’s where
npm run comes in; it adds
./node_modules/.bin to your
PATH. In other words, if you list gulp 3.8 as a
devDependency, you can access the
gulp executable in your
package.json scripts without asking your users to
npm install gulp -g.
npm run watch is a handy shortcut for
./node_modules/.bin/gulp watch. You can do the same thing with mocha.
npm test (which is the same as
npm run test) is a handy shortcut for running all your mocha tests in your
test directory using the nyan cat reporter.
The mocha executable also has some neat command line flags. For instance, the
-g for short) mocha flag lets you only run tests whose names match the given regular expression. In npm >= 2.14.0, you can use
-- to pass extra flags to mocha. For instance, the below commands are equivalent.
An Alternative to Gulp
Gulp is a powerful streaming build system that lets you parallelize compiling your files. It’s a great tool, but it can be overkill for some applications, especially if your team doesn’t have much experience with Node.js streams. The
npm run command can serve as a less-performant replacement for gulp in many use cases. For instance, suppose you have some ES2015 code in
example.js that you want to transpile with babel and then pipe into browserify for use in the browser.
If you wanted to use gulp to compile this, you’d probably use the
gulp-browserify npm modules, which wrap babel and browserify for gulp. However, babel and browserify have command line interfaces, so you can compile this file using Unix-style pipes. Note that the below example requires babel 5.x, it won’t work with babel 6.
Once again, the
./node_modules/.bin part is annoying. Thankfully, if you define a compile script in
package.json, you can just achieve the same result with
npm run compile.
npm run command lets npm function as a versatile task runner in addition to a task manager. Good node.js applications leverage
npm start and
npm test to make it explicit how to run your application and how to test it. Also,
npm run makes including executable npm modules (gulp, mocha, karma, etc.) as
devDependencies more convenient. You can even leverage
npm run and Unix streams to run your build processes without the help of a build system like gulp or grunt. Conceptually,
npm run and the
scripts section in
package.json should define how to do the most common command-line tasks for your application, like starting the application, testing it, and running any transpilers.