Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AilisObrian/31c78f7e20f2ae984d14c3b6b9718980 to your computer and use it in GitHub Desktop.
Save AilisObrian/31c78f7e20f2ae984d14c3b6b9718980 to your computer and use it in GitHub Desktop.
NPM Shrinkwrap Workflow

#NPM Shrinkwrap Workflow

Our workflow consists of the following steps:

  1. Hack on changes and merge to master
  2. CI detects commits to master and runs tests
  3. CI machine runs npm test
  4. Once tests pass, deployable artifact is built on separate system - call this the "build phase"
  5. Build machine runs npm install to install dependencies
  6. Build machine creates gzipped tarball (which includes dependencies) and pushes gzip file to artifact server
  7. 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:

  1. 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
  2. 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

  1. npm prune --production may be the answer (available > 1.4.3), but I still like Solution 2 better

##Solution 2

  1. 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

  1. Check in two versions of shrinkwrap, one that incldues dev dependencies and one that does not
  2. During CI, use shrinkwrap that includes dev dependencies
  3. 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:

  1. npm install <pkg> - installs latest version that satisfies semver in package.json
  2. npm 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment