In the recent 5.0 release, an important feature, which has been optionally available before, was “lifted” into a standard feature: Version pinning of the complete project dependency tree. The need for this feature stems from the desire of any software craftsman to have reproducible builds, i.e. to ensure that no unintentional changes are sneaking into the build output, e.g. due to build platform differences or -updates. Dependency tree pinning has been provided by YARN, Facebook’s own re-implementation of NPM, from the beginning. It was one of the major reasons why YARN was built in the first place. Thus, there is some similarity to the way Spring has pushed JEE to embrace POJO service classes and IO.js has pushed Node.js to develop and adopt new features that many people have long been waiting for, but never got. So dependency tree pinning is available in Node.js and it thus makes sense to use it.
- Use NPM version 5.0 or later or, in case your development machine’s or build system’s OS does not provide that version yet, issue an “npm shrinkwrap” command whenever you add/modify/remove any dependencies from you project.
- Check-in the package lock file – “package-lock.json” for NPM version 5.0 or later and “npm-shrinkwrap.json” otherwise – to the SCM repository and update it whenever you update the “package.json” file.
Now you can be sure that the exact same versions of all dependencies are going to be pulled in, whenever you build the website locally (during development) or directly on the web hosting system (upon deployment). The “npm install” command will automatically make sure that the “pinned” versions of all direct and transitive dependencies are installed.
Because I have been talking about the build process a lot now, I should say that in this little website project, that I am referring to here, NPM is not used as a build tool. I am using it only for dependency management. However, the “dependencies” section of my “project.json” file is nevertheless empty. The project only has “devDependencies”, i.e. build dependencies (or <scope>compile</scope> in maven speak). The build process, to be described in the next post, then generates a deployment artifact that is completely self-contained and executable in any modern browser.
There are, of course, many more details to know about dependency management and NPM. Feel free to comment or drop me a line to let me know of your favorite use case or feature that I have missed.