|
|
|
.\" Generated with Ronnjs 0.3.8
|
|
|
|
.\" http://github.com/kapouer/ronnjs/
|
|
|
|
.
|
|
|
|
.TH "NPM\-SHRINKWRAP" "1" "February 2013" "" ""
|
|
|
|
.
|
|
|
|
.SH "NAME"
|
|
|
|
\fBnpm-shrinkwrap\fR \-\- Lock down dependency versions
|
|
|
|
.
|
|
|
|
.SH "SYNOPSIS"
|
|
|
|
.
|
|
|
|
.nf
|
|
|
|
npm shrinkwrap
|
|
|
|
.
|
|
|
|
.fi
|
|
|
|
.
|
|
|
|
.SH "DESCRIPTION"
|
|
|
|
This command locks down the versions of a package\'s dependencies so that you can
|
|
|
|
control exactly which versions of each dependency will be used when your package
|
|
|
|
is installed\.
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
By default, "npm install" recursively installs the target\'s dependencies (as
|
|
|
|
specified in package\.json), choosing the latest available version that satisfies
|
|
|
|
the dependency\'s semver pattern\. In some situations, particularly when shipping
|
|
|
|
software where each change is tightly managed, it\'s desirable to fully specify
|
|
|
|
each version of each dependency recursively so that subsequent builds and
|
|
|
|
deploys do not inadvertently pick up newer versions of a dependency that satisfy
|
|
|
|
the semver pattern\. Specifying specific semver patterns in each dependency\'s
|
|
|
|
package\.json would facilitate this, but that\'s not always possible or desirable,
|
|
|
|
as when another author owns the npm package\. It\'s also possible to check
|
|
|
|
dependencies directly into source control, but that may be undesirable for other
|
|
|
|
reasons\.
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
As an example, consider package A:
|
|
|
|
.
|
|
|
|
.IP "" 4
|
|
|
|
.
|
|
|
|
.nf
|
|
|
|
{
|
|
|
|
"name": "A",
|
|
|
|
"version": "0\.1\.0",
|
|
|
|
"dependencies": {
|
|
|
|
"B": "<0\.1\.0"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.
|
|
|
|
.fi
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
package B:
|
|
|
|
.
|
|
|
|
.IP "" 4
|
|
|
|
.
|
|
|
|
.nf
|
|
|
|
{
|
|
|
|
"name": "B",
|
|
|
|
"version": "0\.0\.1",
|
|
|
|
"dependencies": {
|
|
|
|
"C": "<0\.1\.0"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.
|
|
|
|
.fi
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
and package C:
|
|
|
|
.
|
|
|
|
.IP "" 4
|
|
|
|
.
|
|
|
|
.nf
|
|
|
|
{
|
|
|
|
"name": "C,
|
|
|
|
"version": "0\.0\.1"
|
|
|
|
}
|
|
|
|
.
|
|
|
|
.fi
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
If these are the only versions of A, B, and C available in the registry, then
|
|
|
|
a normal "npm install A" will install:
|
|
|
|
.
|
|
|
|
.IP "" 4
|
|
|
|
.
|
|
|
|
.nf
|
|
|
|
A@0\.1\.0
|
|
|
|
`\-\- B@0\.0\.1
|
|
|
|
`\-\- C@0\.0\.1
|
|
|
|
.
|
|
|
|
.fi
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
However, if B@0\.0\.2 is published, then a fresh "npm install A" will install:
|
|
|
|
.
|
|
|
|
.IP "" 4
|
|
|
|
.
|
|
|
|
.nf
|
|
|
|
A@0\.1\.0
|
|
|
|
`\-\- B@0\.0\.2
|
|
|
|
`\-\- C@0\.0\.1
|
|
|
|
.
|
|
|
|
.fi
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
assuming the new version did not modify B\'s dependencies\. Of course, the new
|
|
|
|
version of B could include a new version of C and any number of new
|
|
|
|
dependencies\. If such changes are undesirable, the author of A could specify a
|
|
|
|
dependency on B@0\.0\.1\. However, if A\'s author and B\'s author are not the same
|
|
|
|
person, there\'s no way for A\'s author to say that he or she does not want to
|
|
|
|
pull in newly published versions of C when B hasn\'t changed at all\.
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
In this case, A\'s author can run
|
|
|
|
.
|
|
|
|
.IP "" 4
|
|
|
|
.
|
|
|
|
.nf
|
|
|
|
npm shrinkwrap
|
|
|
|
.
|
|
|
|
.fi
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
This generates npm\-shrinkwrap\.json, which will look something like this:
|
|
|
|
.
|
|
|
|
.IP "" 4
|
|
|
|
.
|
|
|
|
.nf
|
|
|
|
{
|
|
|
|
"name": "A",
|
|
|
|
"version": "0\.1\.0",
|
|
|
|
"dependencies": {
|
|
|
|
"B": {
|
|
|
|
"version": "0\.0\.1",
|
|
|
|
"dependencies": {
|
|
|
|
"C": {
|
|
|
|
"version": "0\.1\.0"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.
|
|
|
|
.fi
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
The shrinkwrap command has locked down the dependencies based on what\'s
|
|
|
|
currently installed in node_modules\. When "npm install" installs a package with
|
|
|
|
a npm\-shrinkwrap\.json file in the package root, the shrinkwrap file (rather than
|
|
|
|
package\.json files) completely drives the installation of that package and all
|
|
|
|
of its dependencies (recursively)\. So now the author publishes A@0\.1\.0, and
|
|
|
|
subsequent installs of this package will use B@0\.0\.1 and C@0\.1\.0, regardless the
|
|
|
|
dependencies and versions listed in A\'s, B\'s, and C\'s package\.json files\.
|
|
|
|
.
|
|
|
|
.SS "Using shrinkwrapped packages"
|
|
|
|
Using a shrinkwrapped package is no different than using any other package: you
|
|
|
|
can "npm install" it by hand, or add a dependency to your package\.json file and
|
|
|
|
"npm install" it\.
|
|
|
|
.
|
|
|
|
.SS "Building shrinkwrapped packages"
|
|
|
|
To shrinkwrap an existing package:
|
|
|
|
.
|
|
|
|
.IP "1" 4
|
|
|
|
Run "npm install" in the package root to install the current versions of all
|
|
|
|
dependencies\.
|
|
|
|
.
|
|
|
|
.IP "2" 4
|
|
|
|
Validate that the package works as expected with these versions\.
|
|
|
|
.
|
|
|
|
.IP "3" 4
|
|
|
|
Run "npm shrinkwrap", add npm\-shrinkwrap\.json to git, and publish your
|
|
|
|
package\.
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
To add or update a dependency in a shrinkwrapped package:
|
|
|
|
.
|
|
|
|
.IP "1" 4
|
|
|
|
Run "npm install" in the package root to install the current versions of all
|
|
|
|
dependencies\.
|
|
|
|
.
|
|
|
|
.IP "2" 4
|
|
|
|
Add or update dependencies\. "npm install" each new or updated package
|
|
|
|
individually and then update package\.json\. Note that they must be
|
|
|
|
explicitly named in order to be installed: running \fBnpm install\fR with
|
|
|
|
no arguments will merely reproduce the existing shrinkwrap\.
|
|
|
|
.
|
|
|
|
.IP "3" 4
|
|
|
|
Validate that the package works as expected with the new dependencies\.
|
|
|
|
.
|
|
|
|
.IP "4" 4
|
|
|
|
Run "npm shrinkwrap", commit the new npm\-shrinkwrap\.json, and publish your
|
|
|
|
package\.
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
You can use npm help outdated to view dependencies with newer versions available\.
|
|
|
|
.
|
|
|
|
.SS "Other Notes"
|
|
|
|
Since "npm shrinkwrap" uses the locally installed packages to construct the
|
|
|
|
shrinkwrap file, devDependencies will be included if and only if you\'ve
|
|
|
|
installed them already when you make the shrinkwrap\.
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
A shrinkwrap file must be consistent with the package\'s package\.json file\. "npm
|
|
|
|
shrinkwrap" will fail if required dependencies are not already installed, since
|
|
|
|
that would result in a shrinkwrap that wouldn\'t actually work\. Similarly, the
|
|
|
|
command will fail if there are extraneous packages (not referenced by
|
|
|
|
package\.json), since that would indicate that package\.json is not correct\.
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
If shrinkwrapped package A depends on shrinkwrapped package B, B\'s shrinkwrap
|
|
|
|
will not be used as part of the installation of A\. However, because A\'s
|
|
|
|
shrinkwrap is constructed from a valid installation of B and recursively
|
|
|
|
specifies all dependencies, the contents of B\'s shrinkwrap will implicitly be
|
|
|
|
included in A\'s shrinkwrap\.
|
|
|
|
.
|
|
|
|
.SS "Caveats"
|
|
|
|
Shrinkwrap files only lock down package versions, not actual package contents\.
|
|
|
|
While discouraged, a package author can republish an existing version of a
|
|
|
|
package, causing shrinkwrapped packages using that version to pick up different
|
|
|
|
code than they were before\. If you want to avoid any risk that a byzantine
|
|
|
|
author replaces a package you\'re using with code that breaks your application,
|
|
|
|
you could modify the shrinkwrap file to use git URL references rather than
|
|
|
|
version numbers so that npm always fetches all packages from git\.
|
|
|
|
.
|
|
|
|
.P
|
|
|
|
If you wish to lock down the specific bytes included in a package, for
|
|
|
|
example to have 100% confidence in being able to reproduce a deployment
|
|
|
|
or build, then you ought to check your dependencies into source control,
|
|
|
|
or pursue some other mechanism that can verify contents rather than
|
|
|
|
versions\.
|
|
|
|
.
|
|
|
|
.SH "SEE ALSO"
|
|
|
|
.
|
|
|
|
.IP "\(bu" 4
|
|
|
|
npm help install
|
|
|
|
.
|
|
|
|
.IP "\(bu" 4
|
|
|
|
npm help json
|
|
|
|
.
|
|
|
|
.IP "\(bu" 4
|
|
|
|
npm help list
|
|
|
|
.
|
|
|
|
.IP "" 0
|
|
|
|
|