A package-lock.json file is like the Customer Success Manager at your company: They are both present in every project but you are not sure why and what exactly they do. And you are scared of conflicts with them: especially lock file merge conflicts.
In this article, you are going to learn what's inside a lock file, why it helps with the it works on my machine problem and why it can even enhance the security of your project.
⚠️ I use npm for my examples, but the concepts also apply for yarn or other package managers.
How dependencies work
It turns out, your favourite libraries and packages are often not only built with magic, but with other packages we call dependencies. So when installing for example express in your project, you actually install express and with it everything express devs used to build express.
This is why your node-modules folder suddenly has stuff you did never install: Because the dependencies of your dependencies and their dependencies and their dependencies dependencies are all sitting together making your incredible project work as intended.
Tools like npm, pnpm, yarn or bun are actually taking really good care about this so you don't have to: They resolve cyclical dependencies, they deduplicate dependencies if one is required twice and they also have a way to keep dependencies separate if two packages have the same but need different versions. Cool stuff, I know.
Solving the It works on my machine problem
Let's assume you abandoned finished your last side project and are starting a new one. You install express and your package.json looks like this now:
{
"name": "side-project-i-wont-abandon",
"version": "1.0.0",
"dependencies": {
"express": "^4.18.0"
}
}
Two weeks later, you tell a friend about your cool new side project and he wants to join, so he downloads the code and runs npm install
.
❓Question 1: Will his local version of express be a different one than yours because of the caret which allows upgrading of minor versions and patches? It could be for example 4.18.3...
❓Question 2: What about the dependencies of express? If some updates took place, will these be reflected in his node modules?
😅 Answer: It depends on whether you have a lock file or not.
When you first install all the dependencies, a lock file is created. It saves all the exact versions installed plus the versions of the dependencies. Here is a very small example of express with body-parser as it's dependency:
{
"name": "side-project-i-wont-abandon",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"dependencies": {
"express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"integrity": "sha512-...",
"requires": {
"body-parser": "^1.19.0"
}
},
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-..."
}
}
}
When somebody now runs npm install in another environment with that lock file present, the versions that will be installed will be the ones specified in the lock file.
Therefore, if a lockfile is present, the answer to both questions is NO: the local versions of your friend will be the exact same versions you also have, because they are fixed in the lock file.
If no lock file is present, both answers will be YES - there is a possibility that the installed versions will differ - which could impact the functioning of the project. Or: It works on your machine and I have unexplainable errors I have no idea how to debug.
Why does the lock file improve security?
Imagine that Henry the Hacker has been highly productive and managed to get access to the express npm account. He changed the version 4.18.2 to contain a vulnerability to exploit the projects installing it. (Something like this has happened for example in 2018: event stream incident)
If a third person helping on your project would run npm install
now, version 4.18.2 would be downloaded, because that's the version specified in the lock file. However the lock file also contains a SHA512 hash of the gzipped package. Since adding the vulnerability changed the SHA512 Hash, npm will not proceed with the installation.
npm ERR! Integrity check failed for "https://registry.npmjs.org/express/-/express-4.18.2.tgz"
npm ERR! Expected sha512-<original hash> but received sha512-<tampered hash>
the npm error that makes Henry the Hacker mad
Therefore, your project is secure, as long as you don't update dependencies. 🤯
But wasn't updating dependencies important to maintain your project secure? Well... yes, but also: not always and not right away. If you are interested, I can write about that another time.
Hope this made the topic a little more understandable.
Are there other topics in programming that you just accepted without questioning how they work and why they are there? I would love to hear about them in the comments. ☺️
Photo by Scott Rodgerson on Unsplash
Top comments (0)