DEV Community

Aman Kumar
Aman Kumar

Posted on

Best Practices for Public npm Packages: Lock Files, Publishing & Dependency Management

Confused about whether to commit package-lock.json when publishing to npm? Here's the standard practice for public repositories.


When maintaining an open source project or reusable package on npm, it’s easy to run into uncertainty:

  • Should you commit package-lock.json?
  • How do you ensure consistent dependency resolution?
  • What do end users get when they install your package?

This post breaks down the standard industry practice for open-source npm packages — especially regarding lock files, dependency pinning, CI, and secure publishing.

🔒 Should I Commit package-lock.json?

Yes, commit package-lock.json to your Git repo — but know that:

package-lock.json is ignored when you publish a package to the npm registry.

This means it benefits you and your contributors, but has no direct effect on your package consumers.

Benefits of committing it:

  • ✅ Consistent installs during development
  • ✅ Reproducible CI environments
  • ✅ Easier debugging & auditing
  • ✅ Clear diffs when dependencies are upgraded

📦 What Gets Published to npm?

By default, npm publishes:

  • Your package.json
  • Files not listed in .npmignore (or included in the files field)
  • But not package-lock.json (unless you publish a npm-shrinkwrap.json — more on that below)

TL;DR:

Consumers install dependencies based on your package.json semver ranges, not your lock file.


🛠 How to Pin Dependencies for Safety

Even though you can’t ship a lock file, you can prevent surprises:

✅ Use exact versions in package.json:

"dependencies": {
  "lodash": "4.17.21"   // Not ^4.17.21
}

Enter fullscreen mode Exit fullscreen mode

Avoid semver ranges like ^ or ~ if you want deterministic installs.


📄 What About npm-shrinkwrap.json?

npm-shrinkwrap.json is published with your package and locks the entire dependency tree.
But:
⚠️ It can conflict with your consumers' dependencies
⚠️ It makes updating harder for downstream projects
✅ Useful for CLI tools or apps where you want full control of the install
For libraries, it's not standard to use shrinkwrap.


🧪 CI & Testing Best Practices

Use npm ci in CI — this installs from the lock file and ensures reproducible builds.
Test the final output using:
npm pack
This shows you exactly what your users will get before you publish.
Automate checks before publishing:

"scripts": {
  "prepublishOnly": "npm test && npm run lint && npm run build"
}
Enter fullscreen mode Exit fullscreen mode

🤝 Use Peer Dependencies Wisely

If your library is designed to plug into another framework (e.g. React, Next.js, ESLint):
Declare those as peerDependencies in package.json.
Don’t bundle them in your dependencies.
This avoids version conflicts and duplication.
Example:

"peerDependencies": {
  "react": "^18.0.0"
}
Enter fullscreen mode Exit fullscreen mode

🔐 Security Practices

Run npm audit regularly
Use tools like:
Dependabot
Snyk
GitHub security alerts

Keep your dependencies updated — responsibly!


✨ Final Thoughts

Committing your lock file doesn’t harm your npm package — it helps your team. And while npm won’t publish it, you can still enforce reliable builds and secure installs by pinning versions, using CI properly, and testing your tarballs.
If you’ve ever been burned by a subtle dependency upgrade breaking your users — you’re not alone. Following these practices can save you (and your users) hours of debugging.

Happy publishing!🚀

Top comments (0)