cloned a repo last week. ran npm install. went to make chai. came back — still on "resolving dependencies." stared at the terminal. made the chai anyway. by the time I sat down it had finally finished and my node_modules folder was somehow 400MB for a project with like twelve deps.
next day someone on the PR said "just use pnpm bro." I rolled my eyes. switched anyway. install done in 11 seconds. okay fine. then I ran next dev and saw Turbopack in the output and realised I had no idea what any of this actually was. I just copy commands from Stack Overflow like everyone else.
so here's the thing nobody tells you upfront: npm/pnpm and webpack/vite/turbopack are solving different problems. we mash them together in our head because they all show up in the same terminal session. they're not the same layer.
package managers first
npm install does one job — read package.json, figure out versions, download stuff from the registry, dump it in node_modules. that's the whole gig. the drama is just how it dumps it.
each package can copy its own deps — disk grows fast
npm copies packages into node_modules. simple mental model. duplicate deps = more disk, slower installs.
npm is what ships with Node. you've used it. it works. mostly. the annoying part is hoisting — dependencies of your dependencies can end up at the top level of node_modules, so you can import lodash even though you never added lodash to your package.json. it feels fine until CI breaks because lodash isn't actually in your deps. phantom dependency. fun.
pnpm — why people switch
pnpm keeps one copy of each package version in a global store on your machine (~/.pnpm-store). your project's node_modules is mostly symlinks pointing there. install the same react version across five repos? one copy on disk, not five. monorepo people swear by it. installs are faster. node_modules is stricter — you can only import what you declared. took me a day to stop being mad about that.
yarn and bun — quick notes
yarn was the cool npm alternative for years. yarn berry went weird with PnP mode where there's no node_modules at all — some teams love it, a lot of tools broke. bun is the new hype: install, run, bundle, all one binary, stupid fast, written in Zig. I've had great luck on side projects. hit a random edge case on a work repo and went back to pnpm. ymmv.
now bundlers — different animal
your code has JSX, typescript, css imports, maybe an svg you imported like it's normal. browsers don't understand any of that raw. a bundler translates it into JS the browser can actually run. in dev it also does HMR — you save a file, the page updates without a full refresh. that's the magic you feel when dev is fast.
package manager = gets libs onto your machine. bundler = turns your src into something runnable. switching pnpm won't fix a slow dev server. switching turbopack won't speed up npm install. I confused these for embarrassingly long.
Turbopack · Rust
incremental by design — Next.js dev default
webpack — the one that built the trauma
webpack bundles everything before it serves anything. entire dependency graph, upfront. infinitely configurable — loaders, plugins, a webpack.config.js that could be a novel. create-react-app used it. we all waited 45 seconds for next dev to start in 2019 and thought that was normal. it's not normal. we were just used to it.
vite — the one that felt like cheating
vite flipped the model. in dev it serves native ES modules — browser asks for a file, vite transforms just that file on the fly. heavy deps get pre-bundled once with esbuild (written in Go, comically fast). prod build uses rollup. first time I ran vite after webpack I thought something was broken because it was too fast. it wasn't broken. webpack was just slow.
turbopack — what next.js ships now
same team that made webpack, rewritten in rust. incremental by default — only recompiles what changed, caches the rest. next.js 14+ uses it for dev (next dev --turbo). not a drop-in webpack replacement for every setup yet. for next dev though? yeah, this is the bet. and it's noticeably snappier on big apps.
the rest of the fast gang
turbopack isn't alone. there's a whole ecosystem of "what if we didn't write the slow part in javascript":
esbuild — Go. pre-bundles deps in vite. transform only.
swc — Rust. replaces babel in next.js compile step.
rollup — ESM bundler. vite uses it for prod builds.
rspack — Rust. webpack config compatible, faster.
parcel — zero config bundler. underrated honestly.
bun — zig runtime + bundler + PM. one binary to rule them all.they're not interchangeable. esbuild won't typecheck your code. swc strips types and moves on. turbopack is built into next's dev server specifically. you don't pick these like pokemon — your framework picks for you mostly. next → turbopack + swc. vite project → esbuild + rollup. don't webpack a new project in 2026 unless your team has a very good reason.
so what do you actually pick
next.js? pnpm (or npm if your team fights you on it) + turbopack dev. done. vite + react? pnpm + vite. ancient webpack config held together with duct tape? migrate when it actually hurts, not because a tweet told you to. bun? genuinely fun on side projects. keep pnpm on the thing that pays rent until bun's ecosystem catches up for your specific deps.
none of this is permanent. I used npm + webpack for years. now pnpm + turbopack. in two years something else will be fast and we'll all pretend we always knew. that's fine. just know which layer you're fixing when something's slow.
if you remember one thing
install = package manager. dev server speed = bundler. npm/pnpm/yarn/bun handle the first. webpack/vite/turbopack handle the second. turbopack is next's rust bundler for dev. pnpm is the one that stopped my node_modules from eating my SSD. different tools, different problems. chai stays hot either way.