Logo

dev-resources.site

for different kinds of informations.

How I can get away with never installing npm packages globally

Published at
5/29/2024
Categories
npm
scripts
global
dependencies
Author
rkristelijn
Categories
4 categories in total
npm
open
scripts
open
global
open
dependencies
open
Author
11 person written this
rkristelijn
open
How I can get away with never installing npm packages globally

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Or even if you want to use a specific version of @angular/cli

npx @angular/cli@17 
Enter fullscreen mode Exit fullscreen mode

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 fullscreen mode Exit fullscreen mode

enter npm scripts.

You can simply write:

{
  "scripts": {
    "lint": "eslint ."
  }
}
Enter fullscreen mode Exit fullscreen mode

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"
  }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

So that is why I don't need to install any global dependency. Ever. Because we have npx and npm scripts.

dependencies Article's
30 articles in total
Favicon
Forge Compatibility Reports for module management
Favicon
A Developer’s Guide to Dependency Mapping
Favicon
The Essence of Task Dependencies in Project Management: Definition & Example
Favicon
Wednesday Links - Edition 2024-09-11
Favicon
You Are Not Saved By IaC
Favicon
The Simplest Way to Extract Your Requirements.txt in Python
Favicon
How I can get away with never installing npm packages globally
Favicon
πŸ“š How to see what changed in Composer files
Favicon
Advanced Usage of Dependencies and Models in FastAPI
Favicon
CDK Dependency Strategies
Favicon
How to link a local npm dependency with pnpm
Favicon
It depends! Exploring my favourite Renovate features for dependency updates
Favicon
ERESOLVE unable to resolve dependency tree
Favicon
πŸ“¦ Upgrading Dependencies
Favicon
Python env: be careful with requirements
Favicon
The Better Npm Audit πŸͺ±
Favicon
Choosing dependencies using deps.dev
Favicon
Tips and tricks for using Renovate
Favicon
How to Keep Project Dependencies Up-To-Date
Favicon
Automatically keep project dependencies up to date with Renovate
Favicon
Another cheat sheet for Dependabot
Favicon
When Package Dependencies Become Problematic
Favicon
Automatically manage Python dependencies with requirements.txt
Favicon
Dockerize the Spring Boot Application.
Favicon
Dependency Injection Explained
Favicon
I broke production 3 times in 3 weeks - Part II
Favicon
5 + 1 tips to reduce the noise of Renovate Bot
Favicon
Lock your Android dependencies πŸ”
Favicon
Sorting a Dependency Graph in Go
Favicon
The Essential Guide to Dependency Graphs

Featured ones: