When to Use Global NPM Installs? Rarely
Tags: npm, javascript, yarn, npx
Published: 2019-10-09 10:22:11

---
title: When to Use Global NPM Installs? Rarely
published: true
description: 
tags: npm, javascript, yarn, npx
cover_image: https://media.wired.com/photos/5a5e6e174d9f6733b38b31dc/master/w_2560%2Cc_limit/earthspace-85757273.jpg
---

![Run npm bin](https://thepracticaldev.s3.amazonaws.com/i/k9mm2vjtn0w7icswu9h0.gif)

It is widespread to go on a quick start page of some tool and utility and find instructions similar to this one:
```
npm install - global cool-package
cool start
```
This command is likely to work, but the `--global` should make your eyebrow rise. It is barely needed or recommended to install packages globally.

Well, Why Not?

There are a few reasons for you to avoid installing packages globally:
### But it works for me…
Who of us, developers, have never heard this? Your colleague is trying to run something you just told them to, and… fails. But it works for me, you tell them.
Global packages can be it. If you have some package they do not have, or if there is a version mismatch between your machines, that might be a problem here.

### CI is failing
That problem is similar to the machine mismatch described above. You are setting a CI that is trying to run a command, but it cannot find it. The reason is that the command was part of a package installed locally on your machine.

### That version does not work
One of the worst problems when relying on global packages is version compatibility. If you are working on multiple projects, you are likely to have different versions of packages. Version 3 for project A and version 4 for project B. Sadly, only a single version can be installed globally. You need to work this out.

### Oh, a new node version!
Are you using nvm to manage your node versions? (and if you do not - have a look at it. It is awesome!). If you switch to a new version of a node, even a minor change, your global packages are gone. If you are a very careful maintainer, you will be using the option `--reinstall-packages-from=default`. But if you are like me, you will find sometime later that a specific command does not work, and realize you did not migrate your packages.
Minimizing the number of packages can surely save some precious time.

OK, I am convinced. I will try to avoid using global packages. What is the recommended way to work?

**Keep Them Local**

In most cases, you should keep your packages local to your projects. Save all the packages needed for a project locally with the compatible version or versions range.
```
npm install --save cool-package
or
yarn add cool-package
```
But this raises an issue: when you install a package globally, you can easily run it by typing its executable name:
```
cool start
```
If you try to do that in a local package, you will get an error that the command was not found. NPM installs the executable under the `node_modules/.bin` folder. When running a command, the shell does not search on this path. The NPM global path, on the other hand, is added to the shell path (run echo $PATH to view it).
There are a few ways to solve this:

## Run the command via npm script.

Define the command in the npm script:
```
{
"name": "my-package",
"scripts": {
"build": "cool build",
"test": "cool test"
}
}
```
Now you can run the command by running:
```
npm run build
```
Pro Tip: If your command requires config arguments that start with double dashes, you need to specify it twice when running via npm script. So if you want to run `cool build --watch` You need to run: `npm run build -- --watch` (with two sets of dashes). Otherwise, the command will not be recognized.

## Run with npm bin

However, there are scripts that you want to run only occasionally, and it does not make sense to create a script for each one of them. In this case, you can run it directly by specifying:
```
node_modules/.bin/cool rare-command.
```

A shorter and friendlier way to do it is to use the npm and yarn bin command that returns the path to the executable path, and you can run:
```
$(npm bin)/cool rare-command
```
Have a command that you use often, but you do not want to put it in a script? set an alias for it, such as:
```
alias cl=$(npm bin)/cool
```
This command runs the cool script that is local to the project you run it.

## Use NPX for Local Scripts

Starting NPM 5.2, NPM has a new package called NPX. NPX is extremely powerful, and too often, its powers are overlooked.
Use NPX to run local scripts: By merely typing `npx cool` inside a folder where cool-package is installed, NPX finds the local installation and run the script. If you need to pass any arguments, just send them, without any changes.

## Use NPX for uninstalled Packages

![create Vue app using npx](https://thepracticaldev.s3.amazonaws.com/i/mfaojnc6r1t3edukudyh.gif)

When starting a new project using a CLI, such as Angular CLI, React Create App, or Vue CLI, the project does not yet exist. Therefore, you cannot install the generator package inside the project.

NPX is a lifesaver here, as you can run:
```
npx create-react-app my-app
```
NPX downloads the package to a temp folder and executes the command from there.

In the `create-react-app`, the name of the script is the same as the name of the package. If the package name is different from the command, you can specify the package name to be installed.
```
npx -package @angular/cli ng new my-app
```

## Use Yarn <Command>

When installing Yarn, the bin command is automatically mapped to the yarn command, so you can run it as: 
```
yarn cool
```
(Credit to @bnaya for this excellent comment!)  

## When To Use A Global Package?

After that said, there are cases where global packages are acceptable. The rule of thumb should be to use it when:

- You run the commands mostly outside the context of specific projects.
- You run the command relatively often, and you do not wait for NPX cache every time.
- You are not extremely sensitive to the package's version, or versions do not change often.

For me, an example of such a package is `http-server` . I need it sometimes when I want to run a simple, well, HTTP server from a local folder for development and testing options. In this case, I would install the package globally.
Ah, and do not forget to update the version occasionally. Use `npm outdated -g` to see what packages need an update.

## Conclusion
Run `npm ls -g --depth=0` to see your currently installed global packages. Review them carefully, and always be conscious about the packages you install globally.

More often than not, you can avoid global packages and save yourself some precious debugging time.