I was going to cleverly call this post "npm -g
considered harmful", but unsurprisingly Matt Behrens got there back in 2016 with this excellent article. As a separate lesson, reading it made me think there was no point me writing this because Matt had already explained this so well- but you know what?
It's new Date().getFullYear();
and this pattern is still everywhere, so a little repetition ♻️ and amplification 📣 won't hurt.
⚠️ What's the problem?
I remember saying to a colleague recently, that one of my reasons for liking Linux was the convention of having all your dependencies centrally managed. Everything can be regularly updated in the background, no surprise 6GB downloads whenever I want to start an app (yeah - I'm looking at you, PlayStation), no need to remember where I downloaded the software... just one command.
Of course, I was lying to myself - talking up the life I wish I had, not the tedious reality I actually experience. After running apt-get
it turns out I then need to run npm -g update
. I should also check nvm --install --lts
to ensure that's up to date. Oh, I should also do a flatpak update
since that's where the cool kids are dropping apps now. Then of course, there's that project that decided to use some Python dependencies, so I better look up that oh-so-elegant one liner to pipe pip list
through 50 commands until it hits xargs
. Then, of course, just go through the stragglers that rolled their own update mechanisms because...
(╯°□°)╯︵ ┻━┻
Anyway ┬─┬ノ( º _ ºノ) it was early in the morning when I wrote this. I really do want to use and contribute to your opensource project, but don't make it more work than it needs to be. Luckily, we can fix this together and it's going to make your life as a maintainer easier too.
First, it's not just the overhead of updating packages that's an issue. A global dependency means there's (probably) one version on the system. If I have multiple packages that depend on different versions of that tool, I'm in trouble.
🆘 Save this developer
🚫 So, if you read or are tempted to write documentation that advises this:
npm -g install my-cool-tool
✔️ Instead, I want you to write:
npm --save-dev my-cool-tool
This will add my-cool-tool
as a development dependency for the project. That means there will be an executable accessible as ./node_modules/.bin/my-cool-tool
. Of course, that's an unwieldy path to type each time.
🚫 So, where you were going to just run this:
my-cool-tool
🚧 Instead we're going to make use of "scripts"
section in our package.json
because any command we put there will check our packages ./node_modules/.bin
directory first.
{
"scripts": {
"my-cool-tool": "my-cool-tool"
}
}
✔️ Now, you can run the following:
npm run my-cool-tool
🏄 That's it!
It's mostly just a translation, not a big shift - but I think they pay off is worth it. Now, if I want to use or contribute to your project then I just need to run npm install
and know that I've automatically got my developer environment set up. Who knows, that developer coming back to the project on a new machine a year later... may even be you!
Top comments (1)
npx also helps: Instead of
npm -g install cool-project-generator
justnpx cool-project-generator