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 runnpm 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.