This talk is dedicated to
npm init. It creates
package.json file which describes your projects. Let’s say that you want to use async library for the project. Just type
npm install async --save in the directory where your package.json file is.
sodik@sentinel:/tmp/npm$ npm install async --save
npm WARN package.json firstname.lastname@example.org No repository field.
npm WARN package.json email@example.com No README data
Npm downloaded the dependency to
"description": "Test project",
"test": "echo \"Error: no test specified\" && exit 1"
Npm will install any transitive dependencies if needed for you. Why do I need
--save parameter? Without it npm will just download dependency but won’t update package.json for you. Maybe you just want to try new library but you don’t know if it will work? However in general I would not recommend to do that since you can easily forget to update your package.json (you can “rollback” any your changes in GIT if the library won’t work).
Your colleague wants to join the project, you push it to source control (without node_modules, of course). Now he can simply install all dependencies from package.json with single command
npm install. This needs to be used each time someone adds new dependencies.
Occasionally you (or your colleague) will remove some dependency. In that situation
npm install won’t remove it for others. At least npm will warn you when you list all your dependencies:
sodik@sentinel:/tmp/npm$ npm ls
└── firstname.lastname@example.org extraneous
npm ERR! extraneous: email@example.com /tmp/npm/node_modules/moment
If you are sure that you want remove all “not tracked” dependencies, just type
npm prune and you are done.
As time progresses, your 3rd party dependencies can get updated. Maybe some bug fix or just new functionality was added. You can easily check that.
sodik@sentinel:/tmp/npm$ npm outdate
Package Current Wanted Latest Location
moment 2.0.0 2.10.6 2.10.6 moment
To update dependencies use
npm update --save. You can also only specify specific packages to be updated. Once the package.json is updated, others can simply call
npm install to update their dependencies (actually to fix as such dependencies do not satisfy package.json definition – npm calls them
But how does npm handle versions? Npm assumes semantic versioning (although npm can’t force package authors to comply to it). When you install new dependency, you will find in package.json something like
"moment": "^2.10.6". It means that you want version 2.10.6 or newer but only if there are no breaking changes (i.e. less then version 3.0.0 – as semantic versioning defines). Note that breaking changes works differently for version less then 1.0.0! See example output of npm outdated:
Package Current Wanted Latest Location
babel-core 5.8.33 5.8.33 6.1.2 babel-core
Even though there is version 6.1.2 of babel-core, wanted version is still 5.8.33. If you want to update anyway, you have to do it explicitly and face the consequences 🙂
Caret “^2.10.6” syntax is not the only one, you can use use “1.x” for any “1.*.*” version. There are plenty other syntaxes like “~1.2.3” or even expressions like “1.2.7 || >=1.2.9 <2.0.0”. For more details check the documentation.
So far we have spoken only about dependencies. However in package.json you can have also devDependencies, peerDependencies, bundledDependencies and optionalDependencies. For example you don’t need your test dependencies to run the package, thus they should be installed as development dependencies via
npm install sax --save-dev or just
npm install sax -D. Be default dev dependencies will be installed with normal dependencies. Same holds true for optional dependencies with only exception that failure to install optional dependency won’t result in failure of installation process.
Npm and node.js can be useful not only for client-server applications but also for various utilities. You might want to generate documentation using apidoc or just run your tests with mocha. If you use such utilities across multiple projects (or just use it also outside of your projects), you can install globally. Such dependency won’t be installed in your local directory but will be installed somewhere in your system.
In some cases it is fine but the only drawback is that you can’t manage them (at least not easily) via your package.json. In general I would recommend to put all project dependencies into package.json and install them locally (e.g. you won’t affect different projects with possibly different version of your build tooling). Just use your build tooling (e.g. gulp) to do all work automatically or you can use package.json scripts section.
"lint": "eslint **/*.jsx"
Then you can execute it via
npm run lint. It is even possible to pass additional arguments to the end via ‘–‘:
npm run lint -- --format compact. Or check this trick from stack overflow.