You’ve probably seen many NodeJS articles. You always use NPM to install this or that package, but they never ever talk about it.
This is true even for my own articles. We always take NPM for granted. Yet, what will you do if there was no NPM or no NPM registry?
You will have to write always everything yourself or you will have to go trough the Internet to eventually find something useful.
Even if you do find a module to help you, there will be no way to manage its version. The next time it is updated it might break your app and make it unusable.
What’s worse the modules on which you depend might have their own dependencies, which then they might break. These kind of problems are extremely difficult to fix.
But it doesn’t end here. Those additional dependencies might rely on packages that have different versions but are the same as a package on which you rely on.
It becomes a nightmare to manage.
That is the time when you realize that NPM might be the best thing from the NodeJS community.
It’s no wonder that it has been the most used package manager out there, not just for Node but for any programming language and platform.
It not only solves all problems with installing dependencies but it is providing an enormous list of readily available packages.
It also handles the correct versions and what is even more critical, the correct versions of the dependencies of your dependencies.
NPM is so good, that many package managers for other languages and platforms try to emulate it.
NPM actually consist of two things. The NPM command line tool, which you use with every project and the NPM registry which contains all publicly available modules and packages.
What is an NPM package?
An NPM module is a piece of code, which you can download with
Then you can use it in your project
Just two lines and you are ready! It is that simple!
Such a package can be just a simple one file with a few lines, or it may contain hundreds of files and tons of code.
The NPM Registry
The NPM Registry is the central repository where all publicly available modules are published by both individuals and organisations.
They range from small snippets of code to full blown SDK for some online service.
It is maintained by npm Inc, and they to a great job to keep it always online for all of us.
What happens after you install a package?
It depends on how you installed it. You can install a package either locally or globally.
This command will install the some-package
module in the local node_modules folder.
So if you run the command /path/to/project it will be installed /path/to/project/node_modules.
You don’t need to create node_modules yourself.
All the code will be only inside this folder. Then when you use require('some-package')
for your project at /path/to/project it will automatically know where to look at!
It is a simple convention, which works beautifully.
This is how you should install all your project dependencies, always locally, because this way they only affect your own project.
Global packages
However, sometimes you want a package to be installed globally. You mainly want that when a package contains a tool.
For example, you might use the excellent http-server
for locally testing static
pages.
You can install it globally
And then automatically, you have available the http-server
executable which you
can run with from anywhere.
Listing your installed modules
Once you start installing new packages, you easily might forget what you already have.
This command will show everything installed in your local node_modules folder, including the dependencies of your project dependencies.
That command will show all globally installed packages and their dependencies.
How to always remember with package.json
We’ve talked about installing and checking what is installed, but a project needs more than that.
You not only need to install packages, because packages change from version to version. You need to have the correct versions to be sure that you project will always work.
This is where package.json comes in.
This is an example of how your package.json may look like.
The most interesting part of it is the dependencies section.
It contains all of your project dependencies. It also contains their allowed versions, according to SemVer.
For example "mocha": "^2.3.3"
means that we would accept any non-major but newer
version than 2.3.3, which means all version of kind 2.x.x where x.x. is bigger
than or equal to 3.3.
Another interesting field is devDependencies, which is here to contain all your dependencies which are not needed to run your project, but are required when you are developing it.
For example, you could put here packages related to testing like mocha and should.
Installing dependencies from package.json
This is one of the easiest things. You just go to your project folder where your package.json is stored and run the following:
and all of your dependencies will be installed. When you run
in this case devDependencies will not be installed.
However, in both cases all dependencies will be installed with versions according to what you’ve put in package.json, so that you project runs wihtout a hitch if you put in production tomorrow or in five years.
As a result every developer on your project will have the same stuff and it will work the same.
How do you create package.json?
Yeah, we’ve talked a lot about the package.json and NPM but how do you create it?
Just run the following in your project folder:
And you will be asked a few questions that will fill most of the fields from above, except the dependency fields.
Filling dependencies
Filling dependencies by hand is not awesome, and of course NPM has a very easy
solution to that, too. When installing just add the --save
flag like this:
As a result some-package
with an aprorpiate version will be put in the dependencies
section, and also installed in the local node_modules folder.
If you instead replace --save
with --save-dev
the package will be put in the
devDependencies section.
Let’s automate it
Let’s face it, you always want your packages and their appropriate versions to be part of the dependencies in package.json. So writing it everytime is not optimal.
Instead run the following command once and forever:
Once you do it, you don’t need anymore the --save
flag. Your dependencies will
always be put in your package.json.
Uninstalling
Sometimes you will also want to remove a package
or
one of these commands will then help you.
What prevents different versions of the same package to clash?
So far you’ve been installing, uninstalling, saving packages to package.json.
Now, you’ve got all your dependencies under control. However, you probably realize that they depend also on other modules, which depend on even more, etc.
What does happen when your project depends on a module, and a depedency relies on the same module but on a different incompatible version?
Thanks to NPM, you don’t have to think about it. It handles all of these transparently for you and there is never a clash of versions. It will always work.
Let’s make it strict
In general npm packages follow SemVer, but sometimes they don’t. What’s more some apps need to have the absolute exact version every time in production.
Not only that, but package.json only list your own dependencies, and not the dependencies of your dependencies.
Their dependencies are stored in their own package.json files which you don’t have control over them, and they might be written badly. So badly, that a future version of one of their dependencies can bring your own app down.
For those cases you can run the following command:
It will generate an npm-shrinkwrap.json
package which contains the exact versions
of not only your own dependencies but also of their own dependencies and so on.
It contains your whole dependency tree, with an exact version of every package on which your app relies on directly or indirectly.
Next time you run npm install
it will automatically use this new json file and
will install the exact version of every package and its dependencies.
Best practices when working with dependencies
NPM makes it super easy to work with external packages. What’s more, the NPM registry has a module for almost anything you might think of.
Sometimes you might feel that it is almost like a Lego, where all is done, you just have to assemble the right parts.
Here is the catch, you have to assemble the right parts. You have to choose carefully, what you depend on.
The main best practices to follow are
- Never depend on modules with just 2 or 3 functions.
- If you can write it in less than an hour, don’t use an external dependency.
because
- External dependencies might become incompatible
- External dependencies might be removed from NPM
We’ve seen this happen before, and it has broken many perfectly written web apps.
So carefully select what you depend on.
Next
You know now how to use NPM and all the most useful commands. Your next step is to learn how to structure your projects and NPM is part of that.
We’ve discussed here mainly the usage of NPM as part of your web project, but you can also use it to publish your own NPM modules.
You can also get our super helpful NPM cheat sheet for developers. It has everything you might need so that you don’t need to remember it all. Checkout it out bellow.
Other articles that you may like