Calyroc
← Back to the blog
7/14/20269 min readBy Thomas Prud'homme

npm, Yarn, pnpm, Bun: The Real 2026 Ranking

Four tools, one job — installing JavaScript without losing your day to it. A no-dogma tour, including the choice made on this very site.

JavaScriptToolingPerformance

There's a question we don't ask often enough anymore, precisely because habit has made it feel settled: which package manager runs your project? For a long time, the answer was npm by default, without much thought behind it. That's no longer good enough. In 2026, the choice of package manager has a measurable impact on build time, repository size, deployment reliability — and, very concretely, on how often you're staring at a terminal instead of writing code. This site is itself a case study: built on Bun instead of the default option, a choice we're going to justify line by line rather than just assert.

A bit of history, to understand why there's a debate at all

npm shipped with Node.js in 2010 and was, for a long time, the only serious option. Then, in 2016, Facebook released Yarn to fix two specific problems: slow, non-deterministic installs — two machines could end up with different versions of the same dependencies, a nightmare in production. Yarn introduced the lockfile as a de facto standard, an idea npm eventually adopted too.

pnpm arrived a bit later with a different obsession: disk space. A developer with a dozen Next.js projects on their machine would end up with the same copy of React duplicated ten times across as many node_modules folders. pnpm fixed this with a content-addressed store — each version of a package exists only once on disk, shared across projects via links.

Bun, finally, didn't settle for being just another package manager. It's a complete JavaScript runtime — written in Zig, not JavaScript — that bundles its own package manager, bundler, and test runner. The stated ambition isn't to improve npm at the margins, but to rethink the JavaScript toolchain from the ground up, on the premise that slowness isn't inevitable, just an implementation choice.

The benchmark: what actually matters

Comparing these tools on a single criterion — "which one is fastest" — misses the point. Three axes actually matter for a production project: cold-install speed (the worst case, a CI build environment starting from scratch every time), warm-cache speed (the everyday case, adding a dependency to an already-installed project), and lockfile rigor — its ability to guarantee that what runs locally runs identically in production.

On cold installs, the gap between npm and the other options has widened over successive versions rather than narrowed. Yarn and pnpm land in roughly the same range, with a slight edge to pnpm on large monorepos thanks to its shared store. Bun pulls clearly ahead: the gain comes less from a caching trick than from an architectural choice — a native runtime, without the JavaScript-on-JavaScript abstraction layer that weighs the other tools down.

On lockfile rigor, though, the hierarchy partly reverses. pnpm remains the reference: its deliberately strict node_modules structure prevents a package from reaching a dependency it never explicitly declared — a classic production bug ("works on my machine") that npm and Yarn in classic mode let slide without complaint.

npm: the foundation, not always the wrong choice

npm remains, by a wide margin, the most universally compatible ecosystem — it's the reference format every other tool works hard to stay able to read. For a small project, a library meant for publishing, or a team that prefers the most documented tool and the one least likely to surprise a new contributor, npm remains a perfectly defensible choice. The reputation it often gets for being "slow" has also faded noticeably since it introduced its own local cache in recent versions.

Yarn: two tools under one name

It's worth being precise here, because "Yarn" actually covers two very different things. Yarn Classic (v1) is a maintenance-mode project, no longer under active development — using it on a new project today has little justification left. Yarn Berry (v2 and later), on the other hand, took a radical turn with Plug'n'Play: instead of physically installing packages into a node_modules folder, it references them directly from a compressed cache. The result is dramatic for versioned repository size, but it takes some adjustment — some ecosystem tools, not always updated for PnP, may need extra configuration.

pnpm: the most serious compromise

If the goal is to stay as close as possible to Node.js's standard behavior — a real node_modules folder, maximum compatibility — while still gaining speed and rigor, pnpm is today the most balanced option on the market. It particularly shines in monorepos, where its native workspace support avoids massive dependency duplication across packages in the same repository. It's a choice we recommend without reservation for most teams juggling several projects in parallel.

Bun: why it's the choice made here

This site runs on Cloudflare Workers, via Next.js and the OpenNext adapter — a build chain that runs on every deployment, not just once in development. On that kind of workflow, the difference between a dependency install that takes a few seconds and one that takes a minute repeats itself dozens of times a week. That's time that produces nothing, just breaks concentration.

The second argument is less measurable but just as real: Bun unifies the package manager, script runner, and runtime into a single binary. On a project that constantly switches between `bun install`, `bun run`, and TypeScript scripts executed directly with no intermediate compilation step, that unification removes a source of friction — one tool to know, one version to keep in sync across development machines.

This choice isn't dogma. Bun is a younger project than npm, pnpm, or Yarn, and its compatibility with the Node.js ecosystem — already very broad — is still improving rather than being 100% complete. For a project where stability trumps everything and every dependency has to be vetted with the utmost caution, pnpm remains a more conservative choice, and a perfectly legitimate one.

And on the animation side: Framer Motion or GSAP?

The same logic — no dogma, the right tool for the right job — applies to another central tooling choice on this kind of project: how to animate an interface. This site uses Framer Motion (now simply "Motion") from the first screen to the last: page transitions, the mobile menu, the chatbot, hover micro-interactions. The reason is simple — Framer Motion is designed for React from the ground up, with a hooks-based API (`useMotionValue`, `useScroll`, `whileInView`) that plugs directly into the component model rather than sitting alongside it. For an interface made of dozens of small state animations, it's the most natural option to write and the simplest to maintain over time.

GSAP (GreenSock) answers a different need, and often a complementary one rather than a competing one: scroll storytelling. As soon as the job is to precisely synchronize several elements to scroll position — text that reveals letter by letter, a section that stays pinned on screen while content scrolls horizontally, a timeline with ten steps choreographed down to the second — GSAP, and its ScrollTrigger plugin in particular, offers a level of control that "React-first" tools still struggle to match. It's no coincidence that the personal portfolio of Thomas Prud'homme, the founder of this studio, leans on GSAP combined with Lenis for its smooth scrolling and 3D particle animations — territory where visual storytelling outweighs component architecture.

The question to ask, then, is never "which one is better," but "what problem am I solving." An everyday-use interface — a dashboard, a marketing site, a configurator — benefits from staying inside its framework's native ecosystem: fewer dependencies to load, fewer concepts for whoever picks up the code in two years to learn. A page designed as an experience, where scrolling tells a story, justifies investing in a more specialized tool.

The takeaway

None of these tools is a bad choice on its own — they simply optimize for different priorities: maximum compatibility for npm, monorepo rigor for pnpm, cache flexibility for Yarn Berry, raw speed and toolchain unification for Bun. The real risk isn't picking "the wrong one," it's never asking the question at all and carrying an inherited choice forward without ever measuring its real cost on your own workflow. It's a question we ask ourselves on every new client project, never settled in advance — and it's exactly what led this site to Bun rather than somewhere else.