npm 5 is shipping with package-lock.json, and the irony isn't lost on anyone. After Yarn forced npm's hand by introducing lockfiles in October 2016, npm is finally catching up. This is competition working exactly as intended—but it also exposes some uncomfortable truths about JavaScript dependencies.
What Changed
npm 5 introduces package-lock.json which locks down the entire dependency tree. Run npm install on any machine with the lockfile, and you get identical versions of every package, including transitive dependencies. This matches what Yarn's yarn.lock has been doing since launch.
{
"name": "my-app",
"version": "1.0.0",
"lockfileVersion": 1,
"dependencies": {
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
}
}
}
The performance improvements are also significant. npm 5 is noticeably faster than npm 4, though still not quite matching Yarn's speed.
The Competition Effect
Six months ago, Yarn launched and immediately gained traction. npm's response has been swift:
- Lockfiles for deterministic installs
- Massive performance improvements
- Better offline support
- Improved security with package integrity checking
This is healthy competition. Yarn identified real problems, built a better tool, and npm had to respond. Users win.
But here's the uncomfortable part: these weren't new problems. Deterministic installs have been a pain point for years. Why did it take a competitor for npm to prioritize this?
The Lockfile Wars
Now we have two lockfile formats: package-lock.json and yarn.lock. They're not compatible. Projects need to pick one.
From a staff engineer perspective, this is manageable but annoying:
- Teams using npm should commit
package-lock.json - Teams using Yarn should commit
yarn.lock - CI needs to use the same tool as local development
- Never commit both lockfiles
The real challenge is libraries. Should package authors commit lockfiles? npm says yes for applications, no for libraries. Yarn says yes for both. The community is split.
Deeper Questions
Lockfiles solve the symptom, not the disease. The real issue is that JavaScript has normalized having hundreds or thousands of dependencies, many of which are tiny utilities that could be written in minutes.
Consider: if you need to lock down exact versions of 1,500 transitive dependencies to ensure your app works, what does that say about the ecosystem's stability?
Other languages handle this differently:
- Go vendors dependencies into the repo
- Rust's Cargo has had lockfiles from day one
- Ruby's Bundler pioneered the lockfile approach
JavaScript is learning these lessons later because the ecosystem moved so fast that tooling couldn't keep up.
Practical Implications
For teams today:
- Use lockfiles – npm 5 or Yarn, doesn't matter which, just pick one
- Commit lockfiles – essential for reproducible builds
- Keep lockfiles in sync – run
npm installoryarn installafter pulling - CI must match local – use the same package manager everywhere
The choice between npm and Yarn is becoming less important. npm 5 closes most of the gap. I'd still lean Yarn for greenfield projects (it's faster, has better UX), but npm 5 is totally viable now.
Looking Forward
This competition is making both tools better. npm is iterating faster than it has in years. Yarn is pushing the boundaries on what's possible.
But the fundamental question remains: is our dependency culture sustainable? Lockfiles ensure everyone gets the same versions, but they don't address the risk of depending on hundreds of packages maintained by strangers.
The left-pad incident taught us that npm's ecosystem is fragile. Lockfiles don't fix fragility—they just make it reproducible.
For more on npm 5 features, see the official documentation.