package-lock.json is never published with your package, so it only controls installs inside your own project. npm-shrinkwrap.json has the same format but can be included when you publish, so it fixes dependency versions for people who install your package. Use it for deployed tools, not for libraries.
The one difference that matters
The npm documentation says npm-shrinkwrap.json is identical to package-lock.json with one major caveat: unlike package-lock.json, it may be included when publishing a package. If both files sit in a package root, npm prefers the shrinkwrap file.
Everything else, including the file format and what it records, is shared. Both pin exact resolved versions and integrity hashes.
Which projects should publish shrinkwrap
The docs say shrinkwrap is intended for applications deployed through the registry, such as daemons and command line tools installed globally or as devDependencies. In those cases the publisher wants every installer to get the same tested tree.
For libraries, the docs say it is strongly discouraged. Publishing a shrinkwrap would stop the people who use your library from controlling updates to transitive dependencies. If a vulnerable package sits in your pinned tree, every consumer inherits it until you publish again.
A decision table
| Your package is | Publish shrinkwrap? | Why |
|---|---|---|
| A library imported by other projects | No | Consumers need control over transitive updates |
| A CLI installed globally | Often yes | One tested tree for every install |
| An internal service deployed from the registry | Often yes | Reproducible deploys |
| An application in a repo, never published | No | Commit package-lock.json instead |
What to do in practice
- Always commit package-lock.json for projects you build.
- For a CLI or daemon you publish, generate the shrinkwrap with the npm shrinkwrap command and review it like any lockfile.
- Re-publish when a pinned dependency has a security fix, because installers cannot pick it up on their own.
- Check what goes into the tarball before you publish, as covered in npm pack dry run: check what you are about to publish.
Common mistakes
The first is publishing a shrinkwrap from a library because it feels safer. It freezes your consumers on your choices and leaves them waiting for you to release fixes. The second is assuming package-lock.json protects people who install your package. It does not leave your repository, so those users resolve the newest versions your ranges allow. The third is forgetting that shrinkwrap takes precedence over the lock file when both exist, so a stale shrinkwrap can silently override the lock file you update.
Quick check
Does npm publish package-lock.json?
No. The npm documentation notes that, unlike the lock file, only npm-shrinkwrap.json may be included when publishing.
Why is shrinkwrap discouraged for libraries?
It prevents consumers from controlling transitive dependency updates, so a vulnerable pinned version stays in their tree until you publish a new release.
Safeguard builds an SBOM from your lockfile and flags vulnerable components with reachability analysis. The free scan is at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.