npm
can have one of two different lock files:
package-lock.json
, which is ordinarily always present and is never published.npm-shrinkwrap.json
, which is created with npm shrinkwrap
and usually published.You can only have one of them and in the event that you have both,
npm-shrinkwrap.json
takes precedence. The files are exactly the same
format and in fact all the npm shrinkwrap
command does is rename your
package-lock.json
.
Through the rest of this document we will refer to the package-lock and
package-lock.json
but everything also applies to npm-shrinkwrap.json
.
The name of the package this is a package-lock for. This must match what's in package.json
.
The version of the package this is a package-lock for. This must match what's in package.json
.
An integer version, starting at 1
with the version number of this document
whose semantics were used when generating this package-lock.json
.
Indicates that the install was done with the environment variable
NODE_PRESERVE_SYMLINKS
enabled. The installer should insist that the value of this
property match that environment variable.
These are the modules installed in the node_modules
. Some of these are
dependencies some of these are transitive dependencies (that is,
dependencies of our dependencies).
This is a mapping of package name to dependency object. Dependency objects have the following properties:
This is a specifier that uniquely identifies this package and should be usable in fetching a new copy of it.
1.2.3
)git+https://example.com/foo/bar#115311855adb0789a0466714ed48a1499ffea97e
)https://example.com/example-1.3.0.tgz
)file:///opt/storage/example-1.3.0.tgz
)file:libs/our-module
)This is a Standard Subresource Integrity for this resource.
integrity
that the registry provided, or if one wasn't provided the SHA1 in shasum
.If this module was symlinked in development but had semver in the
package.json
then this is the relative path of that link.
Discussion of the semantics of this will go in the symlinks RFC.
Implementation note: To be implemented post npm@5.
If true, this is the bundled dependency and will be installed by the parent module. When installing, this module will be extracted from the parent module during the extract phase, not installed as a separate dependency.
If true then this dependency is either a development dependency ONLY of the top level module or a transitive dependency of one. This is false for dependencies that are both a development dependency of the top level and a transitive dependency of a non-development dependency of the top level.
If true then this dependency is either an optional dependency ONLY of the top level module or a transitive dependency of one. This is false for dependencies that are both an optional dependency of the top level and a transitive dependency of a non-optional dependency of the top level.
All optional dependencies should be included even if they're uninstallable on the current platform.
This is a record of what specifier was used to originally install this package. This should be used only for git dependencies.
This is a mapping of module name to version. This is a list of everything
this module requires, regardless of where it will be installed. The version
should match via normal matching rules a dependency either in our
dependencies
or in a level higher than us.
Exactly like dependencies
at the top level, this is a list of modules to
install in the node_modules
of this module.
npm init
If neither a package-lock.json
nor an npm-shrinkwrap.json
exist then
npm init
will create a package-lock.json
. This is functionally
equivalent to running npm shrinkwrap
after the current init completes and
renaming the result to package-lock.json
.
npm install --save
If either an npm-shrinkwrap.json
or a package-lock.json
exists then it
will be updated.
If neither exist then a package-lock.json
should be generated.
If a package.json
does not exist, it should be generated. The generated
package.json
should be empty, as in:
{
"dependencies": {
}
}
If the user wants to get a default package name/version added they can run npm init
.
npm shrinkwrap
If a package-lock.json
exists, rename it to npm-shrinkwrap.json
.
Refresh the data from the installer's ideal tree.
The top level name
and version
come from the package.json
. It is an
error if either are missing or invalid.
This is true
if this dependency is ONLY installed to fulfill either a top
level development dependency, or one of its transitive dependencies.
Given:
B (Dev) → C
Then both B and C would be dev: true
.
Given:
A → B → C
B (Dev) -> C
Then all dependencies would be dev: false
.
This is true
if this dependency is ONLY ever either an optional dependency
or a transitive dependency of optional dependencies.
Given:
A (Opt) → B → C
Then all three of A, B and C would be flagged as optional.
Given:
A (Opt) → B → C
D → C
Then A and B would be flagged as optional, but C would not be.
Given:
A (Opt) → B → C
D → A
Then none would be flagged as optional.
If the packageIntegrity
in the package-lock.json
differs from the one
computed from the package.json
then places where the package.json
is
incompatible with the package-lock.json
a new module should be installed.
That is, while the package-lock.json
ordinarily defines the state of your
project, if your package.json
is edited independently it will take
precedence.
The package-lock.json
describes the exact tree that npm
should create.
Any deviation between the package.json
and the shrinkwrap/lock should
result in a warning be issued. This includes:
package.json
but missing from the package-lock.json
package-lock.json
but missing from the package.json
.package.json
whose specifiers don't match the version in package-lock.json
.Warn if the lockfileVersion
in the package-lock.json
is for a different
major version than we implement.
Module resolution from package-lock data works as such:
If install was run with --resolve-links
and a dependency has a link
property then a symlink is made using that. If the version of the
destination can not be matched to the package-lock and/or the package.json
then a warning will be issued.
Otherwise, if a integrity
is available then we try to install it from the cache using it.
If integrity
is unavailable or we are unable to locate a module from the integrity
then:
lockfileVersion
is set:
version
and validate the result against the
integrity
.integrity
:
resolved
, then from
, then `version.from
can be either package@specifier
or just specifier
.Regardless of how the module is installed the metadata in the installed module should be identical to what it would have been if the module were installed w/o a package-lock.
npm rm --save
Currently if you ask to remove a package that's both a direct and a
transitive dependency, we'll remove the package from node_modules
even if
this results in a broken tree. This was chosen at the time because we felt
that users would expect npm rm pkgname
to be equivalent of
rm -rf node_modules/pkgname
.
As you are no longer going to be allowed to put your node_modules
in a
state that's not a valid package-lock, this means this behavior is no longer
valid. Instead we should follow normal rules, removing it from the
dependencies for the top level but only removing the module on disk if
nothing requires it any more.
Installers should ignore any field they aren't aware of. It's not an error to have additional properties in the package-lock or lock file.
Installers that want to add new fields should either have one added via RFC in the npm issue tracker and an accompanying documentation PR, or should prefix it with the name of their project.