npx is a separate executable that has been shipped alongside Node.js and npm since 2017. npx is a flexible tool for running node packages that makes installing npm packages globally largely obsolete. In this article, I'll demonstrate how npx lets you avoid npm install -g, and show a couple other cool things npx can do.

No More ./node_modules/.bin

The primary use case for npx is running executable npm packages, like the Mocha test runner. Suppose you run npm install mocha@5.x in an empty directory. There are three ways you can run Mocha from this directory:

  • ./node_modules/.bin/mocha
  • Add a script to your package.json: {"test":"mocha"} and then run npm run test.
  • npx mocha. With npx, you don't need to add a script or prefix mocha with .bin.

The first approach is cumbersome because you need to set up tooling or type out ./node_modules/.bin every time. The second approach is better, but has a gotcha when you need to use command line arguments. Suppose you only wanted to run tests that have 'foo' in the title. You can run the below command.

./node_modules/.bin/mocha -g "foo"

To pass the -g command line argument to Mocha through an npm script, you need to add -- before the command line argument. To experienced Node.js developers from the pre-npx days, using -- is second nature, but this is a common pain point for beginners.

npm test -- -g "foo"

npx passes command line arguments transparently to the executable, so you don't need -- anymore.

npx mocha -g "foo"

Install and Run

Another great use case for npx is scaffolding tools, like yo or create-react-app. Before npx, I was ok with installing scaffolding tools with -g. Now, there is no need because npx also automatically installs for you.

For example, suppose you don't have create-react-app installed anywhere. You can still run npx create-react-app@2.x my-new-project to scaffold a React app in the my-new-project directory. As an added bonus, npx won't put create-react-app in your ./node_modules or install it globally. This means you don't have to worry about dangling old versions of create-react-app.

$ npx create-react-app@2.x my-new-project
npx: installed 63 in 1.395s

Creating a new React app in /home/test/my-new-project.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...

+ react@16.8.6
+ react-dom@16.8.6
+ react-scripts@2.1.8
added 1842 packages in 22.348s
You are running Node v8.9.4.
$ 
$ npm list -g | grep "create-react-app"
$
$ ls node_modules | grep "create-react-app"
$ 

Another neat use case is starting a MongoDB replica set with one command using run-rs.

$ npx run-rs --version 4.0.4 --shell
Downloading MongoDB 4.0.4
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 68.1M  100 68.1M    0     0  10.9M      0  0:00:06  0:00:06 --:--:-- 11.8M
Copied MongoDB 4.0.4 to '/home/val/.npm/_npx/9123/lib/node_modules/run-rs/4.0.4'
Purging database...
Running '/home/val/.npm/_npx/9123/lib/node_modules/run-rs/4.0.4/mongod' [ 27017, 27018, 27019 ]
Starting replica set...
Started replica set on "mongodb://localhost:27017,localhost:27018,localhost:27019?replicaSet=rs"
Running mongo shell: /home/val/.npm/_npx/9123/lib/node_modules/run-rs/4.0.4/mongo
rs:PRIMARY> db.version()
4.0.4
rs:PRIMARY> 

Running a GitHub Repo

npx can run anything that has a bin in its package.json. That means it can run GitHub gists. It can also install and run an entire GitHub repo, just like how npm can install from GitHub. For example, this sample-server GitHub repo starts a web server on port 8081 that always prints "Hello, World". You can use npx to run this GitHub repo:

$ npx https://github.com/vkarpov15/sample-server
npx: installed 1 in 1.619s

npx can run this repo because there's a bin property in the package.json. npx will look for this property and run the file specified in the bin property.

You can then hit the web server with curl:

$ curl http://localhost:8081
Hello World!
$

Moving On

npx can save you a lot of time and effort. It can do much more than running locally installed executables without ./node_modules/.bin. For example, you can use npx to install and run the latest version of a release script every time, so you don't have to update the release script version in dozens of package.json files. Check out npx and see what other use cases you can come up with.

Found a typo or error? Open up a pull request! This post is available as markdown on Github
comments powered by Disqus