One small file that is often ignored in a JavaScript project is the lock file.
package-lock.json for npm.pnpm-lock.yaml for pnpm.yarn.lock for Yarn.
Commit it.
Why?
Your package.json usually doesn’t define the exact version of every dependency.
For example:
"react": "^19.0.0"
The ^ means npm can install a newer compatible version.
Today you might get:
react 19.0.0
Next month, another developer might get:
react 19.1.0
And one day, your CI/CD pipeline could install yet another version.
That’s where the lock file helps.
It records the exact dependency versions that were resolved, including transitive dependencies.
So instead of:
package.json - "Give me a compatible version"
you get:
package.json - lock file ↓ "Install exactly what we tested"
This is especially important in teams and production systems.
A developer’s machine, CI server and production environment should ideally be using the same dependency tree.
With npm, that’s one reason npm ci exists.
With pnpm:
pnpm install --frozen-lockfile
can ensure the lock file isn’t silently changed during installation.
The lock file also makes debugging easier.
If an application suddenly breaks after a dependency update, you can see exactly which versions changed.
Without a lock file, dependency resolution can become unpredictable.
So my simple rule is:
package.json says what you want.
The lock file says exactly what you installed.
If you’re building a serious application, commit the lock file.
Don’t add it to `.gitignore.
Your future self – and your CI/CD pipeline – will thank you.