For any node application there are two sources of truth for what the dependency tree should look like:
- package.json
- node_modules/
When you run a shrinkwrap command there are three workflows you can use.
npm ls && npm shrinkwrap
npm ls
will shout and ERR if node_modules & package.json do
not agree. We will only create a new npm-shrinkwrap.json
if
node_modules and package.json agree about what our dependencies
are.
npm shrinkwrap
Here we just shrinkwrap the node_modules/ as is and completely ignore what the package.json says.
rm -rf node_modules;
rm npm-shrinkwrap.json;
npm i;
npm shrinkwrap;
Here we do not care what node_modules/ says it's a temporary artifact. we blow it away and create a fresh node_modules tree from package.json at this moment in time, we then serialize that. Effectively serializing package.json into npm-shrinkwrap.json
If you favor Workflow 1
then you will have to handle any conflicts
as they happen.
This includes running npm install
without a --save
flag and editing
package.json
by hand.
This also includes changing branches where you checkout out a new
package.json
and your node_modules/ tree no longer agrees
If you favor Workflow 2
then you need to ensure node_modules
is
always the source of truth. This means you must get node_modules
into the correct shape every time you checkout a different branch
or pull in changes from master.
You also need to ensure that any changes to node_modules are added
to the package.json otherwise you will commit an npm-shrinkwrap.json
that shouts at you when you run npm ls
.
If you favor Workflow 3
you cannot edit or manage your node_modules.
It is not possible to manually dedupe binary deps for faster installs.
You will also need to run your tests AFTER you run the shrinkwrap command because the state you create is a new untested state. With the other workflows where node_modules/ is truth you can run your tests before running shrinkwrap since running shrinkwrap wont mutate node_modules/
You will also have a slow shrinkwrap process since every call to shrinkwrap will cause a complete fresh install. Where as the other workflows just run shrinkwrap which is fast (~1s) compared to fresh install (~10m)