Pin your dependencies in package.json to increase your project's health
Avoid problems like "it works on my machine" issues and security flaws. (4 min)
When you manage a JavaScript project, especially one using Node.js, npm, or yarn, your package.json
plays a crucial role.
Your package.json
defines your project’s dependencies - the external packages and libraries your project relies on to work.
Properly managing these dependencies ensures the project runs consistently and reliably across different environments.
Possible versions in your package.json
In your package.json
you can have 4 types of versioning for your dependencies:
The caret (`^`) version:
It allows changes that do not modify the left-most non-zero digit in the version number, introducing minor updates and patches automatically.
Example:
{
"name": "https://thetshaped.dev/",
"version": "1.0",
"dependencies": {
"react": "^18.2.0"
}
}
For example, the next time you run npm install
, the react
version could resolve to 18.3.0
or 18.2.3
.
The tilde (`~`) version
It allows changes that update only the patch version automatically.
Example:
{
"name": "https://thetshaped.dev/",
"version": "1.0",
"dependencies": {
"react": "~18.2.0"
}
}
For example, the next time you run npm install
, the react
version could resolve to 18.2.3
.
The greater than (`>=`) version
It allows changes that update the major version automatically.
Example:
{
"name": "https://thetshaped.dev/",
"version": "1.0",
"dependencies": {
"react": ">=18.2.0"
}
}
For example, the next time you run npm install
, the react
version could resolve to 19.0.0
.
The exact (or pinned) version
Example:
{
"name": "https://thetshaped.dev/",
"version": "1.0",
"dependencies": {
"react": "18.2.0"
}
}
For example, the next time you run npm install
, the react
version will resolve to 18.2.0
which is the same version.
Why it is important to pin your dependencies in package.json
Pinning dependencies means specifying exact versions of dependencies instead of using version ranges like `~`, `~`, or `>=`.
This practice is key to maintaining consistency and reliability across all environments.
It ensures everyone is working with the exact same modules.
Benefits
Consistency - pinning dependencies prevents issues like “it works on my machine” by ensuring every environment uses identical dependency versions.
For example, specifying"react": "18.2.0"
instead of"react": "^18.2.0"
guarantees that the same react version will be installed everywhere.Reliability - by using exact/pinned versions, you will have fewer surprises from updates that introduces bugs and break the functionality.
Security - pinning versions helps avoid automatic updates to new versions that may have security vulnerabilities or compromised code.
Drawbacks
Maintenance Overhead - regularly updating dependencies to include new features or fixes of bugs could be time-consuming but it is necessary for the project’s health and stability.
Outdated Packages - if the packages are not reviewed and updated regularly, you might miss critical enhancements or security patches.
Best Practices for pinning dependencies in your package.json
1. Use precise versions.
Always specify exact versions in package.json
to avoid any ambiguities.
2. Regularly update dependencies. Use automations and tools.
You can integrate automation tools like Renovate or Dependabot into your project to help keep your dependencies up-to-date by automatically creating pull requests for each update.
These PRs can be configured to be merged automatically if all checks pass. That’s why it’s important to have a good test coverage to ensure no bugs are introduced.
3. Automate security patches.
Use tools like npm audit or Snyk to automatically detect vulnerabilities and suggest or event apply patches without manual oversight.
4. Use version locking.
By using package-lock.json
or yarn.lock
files you enforce the use of the exact dependencies versions recorded during the last successful installation. This ensures consistency and reliability.
⭐ TL;DR
Pinning dependencies in
package.json
is crucial for the project’s health, stability, consistency, and security.Use exact versions (ex:
"react": "18.2.0"
).Regularly review and update your dependencies in
package.json
.Use automation tools like Renovate, Dependabot, npm audit or Snyk, in your project to help keep dependencies up-to-date and avoid security vulnerabilities.
👋 Get in touch
You can find me on LinkedIn or Twitter.
This newsletter is funded by paid subscriptions from readers like yourself.
If you aren’t already, consider becoming a paid subscriber to receive the full experience!
Think of it as buying me a coffee twice a month, with the bonus that you also get all my products for FREE.
You can also hit the like ❤️ button at the bottom to help support me or share this with a friend to get referral rewards. It helps me a lot! 🙏
🗞️ You may also like
📣 Articles worth reading
How Facebook Scaled Live Video to a Billion Users by
The 3 Big Mistakes That Almost Cost Me My Promotion (And How You Can Avoid Them) by
Engineer’s guide to convincing your Product Manager to prioritize technical debt by
Build Your Credibility As You Grow by
Keep is Simple, Software Engineer (KISS) by