10 Cool Things You Probably Didn't Realize npm Could Do #
OMG UPDAET! 2011-06-19
Some of this is no longer 100% accurate, which shouldn’t be very surprising, since it was written 7 months ago, and npm had a major version update since then.
Check out the node blog for some of the 1.0 changes.
npm is the node package manager. Once upon a time, I would have said “a” node package manager, and the humbler part of me would like to pretend that that’s still the case, but SCREW THAT HUMBLER SIDE, I’m feeling egotistical and braggy today, so today it’s THE node package manager.
Also, I’m writing a “head -n 10” blog post, so it’s basically a license to be a complete ass.
Yeah, it’s that kinda day. I think tomorrow, Imma eat a turkey. So there.
You probably know that npm can install stuff, publish stuff, remove stuff, and that it makes dependencies magically work. You may even know that it runs without being burdened by unnecessary semicolons.
If you’re a node veteran, you may even already know about some of these lesser-known features. But I’m hoping that at least one of them is a bit surprising, even for old timers and core node devs.
1: Handle multiple versions of the same thing at the same time
One of the reasons I wrote npm is that package managers put you in dependency hell, and I simply can’t abide that.
npm keeps all its installed packages organized in name/version
folders, and versions all the public stuff. Then, one of them is
“active” at any given time in the global space. (That’s what you’ll see
if you install multiple versions of “foo” and then drop into the repl and
do require("foo")
.)
But here’s where it gets cool: Let’s say that you installed foo@1.0.0
and foo@2.0.0
. Now, you have bar@1.0.0
that depends on foo@1.0.0
,
and baz@1.0.0
that depends on foo@2.0.0
, and quux@1.0.0
that
depends on bar
and baz
.
Here’s a diagram:
quux@1.0.0
|
+-- bar@1.0.0
| |
| `-- foo@1.0.0 \
| \
`-- baz@1.0.0 > Conflict?
| /
`-- foo@2.0.0 /
In most package manager systems, quux would simply never be installable. It needs two packages that can’t coexist because they have competing dependencies. Or, you’d have to name things stupidly, and bar and baz would have tobe aware of one another.
npm handles that all for you. Try it. It works.
It’s MAGIC. (Also, it’s the commonjs module system’s built in separation of scope that doesn’t require that the path be a single consistent thing.)
2: Be gone at runtime
npm doesn’t load your modules. It installs them. Then you can even do
npm rm npm
and it’ll remove itself. All the modules you installed?
Yeah, they still work.
It does this by setting up things in the proper places so that node’s very simple module loader can find them when it needs them.
Most package managers are sort of hybrid loader/installer things. npm is first and foremost a dependency manager. It puts things in place, and then ducks out of the way so that it’s not all in your face telling you how to write your programs.
3: Structure your program any way you want
…provided, of course, you describe that structure in a package.json file.
That is, you can put all your node modules in a folder called “src” or
“lib” or “path/to/my/awesome/modules”. npm doesn’t care. In fact, it
doesn’t even need to be a node program. If you can describe the package
in a package.json file, you can install literally anything. I’m
waiting for people to figure this out, and see something awful and
hideous like npm install vim
.
A lot of people have objected to this feature. They called me crazy and said that we need to form a committee and decide on a set of conventions. Some even went so far as to pound fists on tables, and declare that madness will surely result from my freewheeling insanity!
To them, I say, HA! JavaScript is at its heart an anarchic language, forged in the great battles of Browsers, lit by the flicker of a thousand animated gifs depicting construction workers. It bears many scars from those dark days, but it also resulted in a strong and vibrant community, all of whom have strong opinions and found their way here because they could not agree on much of anything.
npm welcomes your strife. Like JavaScript itself, it doesn’t judge you.
Read through npm help json
to learn what you can put in your
package.json file.
4: Start a package.json file for you
If you run npm init
in a folder, it’ll ask you a few questions, and
then write out a package.json file.
The init command is pretty new, and doesn’t do much. But sometimes all you need is a little nudge to get started.
5: Verify sha1 hashes of packages
As of version 0.2.9, sha hashes get generated for all packages as they get published, and then are verified after being downloaded.
Checksumming is one of those things where everyone feels a little safer knowing it’s there, but no one usually pays much attention to it. When it works, it’s silent, and that’s great.
The good news is that, now, if there’s some kind of error downloading something, or if something gets corrupted in transit in any other way, then npm will stubbornly refuse to proceed.
(You have to compile node with openssl crypto support for this to work.)
6: Shut The Hell Up
Sometimes you just need to show your packager who’s boss. “Shutting up” is a feature. By
setting the loglevel
config, you can make npm anywhere from completely
silent to ludicrously noisy. The levels are: silent, win, error, warn,
info, verbose, and silly.
- silent: completely silent. Zero logging output.
- win: Just the “npm ok” or “npm not ok” message at the end.
- error: When something unexpected and bad happens.
- warn: When something odd or potentially dangerous is happening.
- info: Helpful information so you can track what’s happening.
- verbose: Even more. Perhaps just a wee bit obnoxious, even.
- silly: Completely fuckin crazy, man. Dump everything. Whole objects, you name it, whatever.
Like any configuration option, you can set the loglevel in a few ways.
To set it for just one command just add --loglevel silent
to the
command. This is particularly handy if something breaks, and you want
to provide a bit more debugging output with --loglevel verbose
.
To set it for your user account, you can do npm config set loglevel
win
.
To set it globally for all users on the machine, you can do npm config
set loglevel info --global
.
You can also set it in the environment if that floats your boat. Any
config option can be set by the npm_config_<blerg>
environ, so doing
export npm_config_loglevel=verbose
will affect all subsequent npm
commands.
Oh, and if those npm config set
and npm config get
commands get
tedious, you can just do npm c edit
to open up the config in your
favorite editor.
See npm help config
for more info.
7: Abbreviate commands
If you’re anything like me, then you drink a lot of coffee, hate extra typing, and are awesome. But mostly the typing. Let’s focus on that.
Is “install” just too long for you? Try npm inst connect
. Bam. Done.
Anything that is unambiguous will work just as well. I don’t have this
logic implemented for arguments and package names, but that’s on the
roadmap. It uses the abbrev
program, and you can use it in your
programs, too. npm i abbrev
to get it.
The most common commands even have super short shorthands, because I love you.
- i: install
- r, rm: uninstall
- ln: link
- ls: list
- bn: bundle
- up: update
- c: config
If you think it stops there, you’re wrong. So wrong. Go sit in the corner.
In the npm source folder, there’s a file called npm-completion.sh
.
Source that bad boy in your bashrc or whatever, and you’ve got tab
completion.
Tab completion! The penultimate feature of any unix program, second only to tab completion that works and is helpful!
This is where you come in. Check out what it’s doing. Dig into the
code. Make it better. Right now it can just tab-complete npm commands,
not package names or other useful things. But if you hack away on the
lib/completion.js
file, you can make it awesomer.
8: Get help on anything
npm has a ton of documentation. In fact, the biggest documentation problem at the moment in npm is that there’s too much of it, and it’s probably impossible for any non-robot to read all if it in a reasonable amount of time.
In case you’re not a robot, here’s how you can get the most out of the docs:
- run
npm
without any arguments. This’ll show you what you can do. It lists out the commands and the help topics. - run
npm command -h
to quickly view the arguments that command expects. This is handy when you forget how to do something that you knew how to do, and you just need to remember how you did it. - run
npm help <topic>
to get more detailed manpage-style documentation. For general info about npm itself, you can runnpm help npm
. This page has a few pointers based on your use cases. Check it out.
9: View specific fields on published packages
The npm view
command was pretty lame for a while. Basically it just
fetched data from the registry and then dumped it to the terminal. But
now, it’s so much more.
Specify a package name (in the form of name@version
or name@latest
or name
or even name@">=1.2.3"
for ranges), and optionally one or
more fields, and it’ll pull just those fields out and show them to you.
It operates smartly on arrays, and parses out the url
and email
fields from contributors and author names. So, if you do this:
npm view npm contributors.name
then you’ll get a list of all the contributor names in npm. If you just do:
npm view npm contributors
then you’ll see the list of contributors in the "name (url) <email>"
format.
10: Bump your package version FOR YOU OMG HOLY CRAP WHAT!?
Yeah. That’s right.
It’ll even commit the change, and tag it for you, if you do it in a git repo. Just run:
npm version 1.2.3
It’ll open up your package.json file, change the version to 1.2.3, git
add
it, git commit
it, and git tag v1.2.3
it.
If your git repository is unclean, then it’ll recoil in horror at the dirty, and tell you to get your act together. (Of course, if you’re not using git, then it won’t do the git stuff. It’ll just change the json and write it back to package.json.)
11: Bundle all your dependencies into the package itself
When you use the npm bundle
command, npm will put all your
dependencies into the node_modules
folder in your package. But it
doesn’t stop there.
If you want to depend on something that’s not on the registry, you can do that. Just do this:
npm bundle install http://github.com/whoever/whatever/tarball/master
This will install the contents of that tarball into the bundle, and then you can list it as a dependency, and it won’t try to install it when your package gets installed.
This also is handy if you have your own fork of something, and would prefer not to change the name.
In fact, you can run almost any npm command at the bundle. To see
what’s inside, you can do npm bundle ls
. To remove something, do npm
bundle rm thing
. And, of course, you can install multiple versions and
activate the one you want.
12: Change the very laws of mathematics itself!!
There are 13 things in this list of 10 things.
npm IS JUST THAT AWESOME.
13: Always be lowercase
If you see npm referred to as “NPM” anywhere except right there in this sentence, then you know that I didn’t write it. “NPM” is the National Association of Pastoral Musicians. If you need some church music, use NPM. If you want node packages installed, then you need npm.
Other things that didn’t make this list because they were too common or not awesome enough
- Cache registry requests using etags.
- Run arbitrary scripts to start, stop, restart, and test packages.
- Set deprecation messages to keep people from using old versions of your stuff.
- compile node addons automatically if it sees a wscript file.
- rebuild packages in a single command so that you can easily keep up
with node ABI changes.
npm rebuild
- Manage owners of a project with the
npm owner
command. - Edit package contents. See
npm edit
. (When used asnpm bundle edit
it’s especially handy.) - Be used as a library in node programs. (Check the readme for a quick how-to, or
cli.js
for an example of using npm programmatically.)
Happy Thanksgiving, Americans. And non-Americans, Happy Random Thursday When All Your American Friends Are Not Online Much!