#NPM Shrinkwrap Workflow
Our workflow consists of the following steps:
- Hack on changes and merge to master
- CI detects commits to master and runs tests
- CI machine runs
npm test
- Once tests pass, deployable artifact is built on separate system - call this the "build phase"
- Build machine runs
npm install
to install dependencies - Build machine creates gzipped tarball (which includes dependencies) and pushes gzip file to artifact server
- Artifact can be deployed to staging or production environment
We check in the shrinkwrap file to lock down our dependency versions, however...
Consequences of proceeding workflow:
- We must include dev dependencies in shrinkwrap file
npm shrinkwrap --dev
since CI needs dev dependencies to run tests. Locking down dev dependencies is probably a good idea since tests in CI will be run with exact same versions of test libraries that were used to test in development - Deployable artifact is created by running
npm install
, which will include test dependencies in tarball that's deployed to production, which is not ideal
The problem is, npm install --production
blindly installs depdencies listed in npm-shrinkwrap.json file, which may include dev dependencies.
To solve the problem, there are two solutions I can think of:
##Solution 1
- npm prune --production may be the answer (available > 1.4.3), but I still like Solution 2 better
##Solution 2
- Modify behavior of
npm install --production
so that if a shrinkwrap file exists, only install dependencies from shrinkwrap file that are included in the dependencies section of package.json
##Solution 3
- Check in two versions of shrinkwrap, one that incldues dev dependencies and one that does not
- During CI, use shrinkwrap that includes dev dependencies
- When creating deployable artifact, use shrinkwrap that does not include dev dependencies
Consequences: Extra script/code necessary to rename 'correct' shrinkwrap file to npm-shrinkwrap.json in different environments
##Links to related GH issues:
npm/npm#3436 npm/npm#3881 npm/npm#3675 - Yikes, luckily for us, we're using shrinkwrap --dev
#Updating dependencies in shrinkwrapped project
Two ways to udpate dependencies:
npm install <pkg>
- installs latest version that satisfies semver in package.jsonnpm update
- updates all packages to latest that satisfy semver in package.json
The problem is that it is easy to forgot to update and check in the shrinkwrap. You may develop and test against updated versions of libraries, but then when someone else pulls down your changes and runs npm install
, the shrinkwrap will dictate what gets installed.
One solution I thought of was to run npm shrinkwrap
in postinstall script, but this does not get triggered when installing individual packages. It also appears that postupdate scripts do not get executed after npm update
for some reason.
##Solution: Implement an npm shrinkwrap --dry-run option which will output the result of shrinkwrap, but not write npm-shrinkwrap.json, or just a npm shrinkwrap --check option which will tell you if your shrinkwrap is out of date. This command can then be run in a pre-commit hook and prevent commits if the shrinkwrap is out of date.
#Inconsistent shrinkwrap
npm/npm#3581 https://github.com/goodeggs/clingwrap goodeggs/clingwrap#1
##Hacky Solution: remove all the resolved keys in a pre-commit hook