My belief is that when you clone a git repository all code, settings and tools should be contained in that cloned repo; the directory. It should not contaminate the system, not by tools, not by environment variables, maybe a bit for the platform.
Scope
This article will not discuss the use of .env
file for maintaining environment variables or the .nvmrc
to enable automatically switching to the proper node version. Also it will not include info about .npmrc
file to e.g. lock the node version.
Trigger to write this article
So many README.md files or manuals say things like:
// https://angular.io/guide/setup-local
npm install -g @angular/cli
More candidates like these are, but not limited to:
eslint
prettier
create-react-app
webpack
@vue/cli
nx
Why would you want to do this? You have now local packages to maintain, and you can't use it across different projects that may have different versions of that software package.
Enter npx
npx is a package runner tool that comes with npm 5.2.0
and higher. The current version when writing this article is npm 10.8.0
It is designed to execute binaries from Node packages without globally installing them. However, NPM documentation suggests globally installing certain packages, especially when they are CLI tools that will be used frequently across different projects.
So instead of installing globally you can execute:
npx @angular/cli
Or even if you want to use a specific version of @angular/cli
npx @angular/cli@17
You have to type less, you can specify exact versions and you don't contaminate the developer's machine.
But what about package.json
?
The package.json
file serves as the cornerstone of any Node.js project, acting as the project's manifest. It provides critical metadata such as the project’s name, version, and author, and it specifies the dependencies and devDependencies required for the project to run and be developed. Additionally, package.json
defines custom scripts that automate common tasks like building, testing, and starting the application. This file ensures consistent environment setup, simplifies dependency management, and facilitates project configuration, making it an essential tool for maintaining and sharing Node.js projects.
So if it is a dependency of the project, why not add it to the dependencies
, devDependencies
or even peerDependencies
?
You can specify the exact versions, using carot-minor (^) or tilde-patch (~) imports. It even automatically updates when fixes arrives.
But I can't run the tools' commands directly from the shell?
Well, fair point. If you want to run e.g. eslint, you don't want to enter:
node_modules/eslint/bin/eslint.js .
enter npm
scripts
.
You can simply write:
{
"scripts": {
"lint": "eslint ."
}
}
So why does this work?
NPM scripts can locate executables in the project's node_modules/.bin directory without needing to specify the full path. I does also look at the project itself and the global installed packages and eventually just performs the command hoping the OS will pick it up.
So that does mean that you can also install e.g. nx
and use a script to alias the nx
command:
{
"scripts": {
"nx": "nx"
}
}
But what about passing arguments?
You can't simply pass arguments to nx
as nx --help
, you need to pass them as positional arguments using an extra pair of dashes --
like so as described in the npm documentation:
nx -- --help
So that is why I don't need to install any global dependency. Ever. Because we have npx
and npm
scripts
.
Top comments (0)