| .\" Generated with Ronnjs 0.3.8 |
| .\" http://github.com/kapouer/ronnjs/ |
| . |
| .TH "NPM\-SHRINKWRAP" "1" "December 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\. The "package\.json" file is still |
| required if you want to use "npm install"\. |
| . |
| .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 |
| npm help You can use npm\-outdated to view dependencies with newer versions |
| available\. |
| . |
| .SS "Other Notes" |
| 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 |
| Since "npm shrinkwrap" is intended to lock down your dependencies for |
| production use, \fBdevDependencies\fR will not be included unless you |
| explicitly set the \fB\-\-dev\fR flag when you run \fBnpm shrinkwrap\fR\|\. If |
| installed \fBdevDependencies\fR are excluded, then npm will print a |
| warning\. If you want them to be installed with your module by |
| default, please consider adding them to \fBdependencies\fR instead\. |
| . |
| .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 package\.json |
| . |
| .IP "\(bu" 4 |
| npm help ls |
| . |
| .IP "" 0 |
| |