"Bundling started as a workaround for browser limitations. In 2026 the browser caught up — and 'bundle by default' became a habit, not a requirement."
Why Bundling Existed
In the 2010s, browsers couldn't load ES modules natively. Every import statement triggered a separate network round-trip; a hundred small modules meant a hundred requests on every page load. Bundlers (webpack, browserify, then Rollup, then esbuild, swc, Vite, Turbopack) solved this by:
- Walking the import graph statically.
- Concatenating all the modules into a small number of output files.
- Minifying, tree-shaking dead code, and lowering newer syntax for older browsers.
For shipping to the browser, that's still useful (HTTP/2 helps, HTTP/3 helps more, but tree-shaking is still real). For server-side Node code? Mostly cargo cult.
Server-Side Node Doesn't Need Bundling
Yet most TypeScript Node services bundle anyway, often because their templates do. The cost: a build step in dev, a build step in CI, source maps to debug, a transpile pass even when the runtime already understands the syntax (Node 22+ runs modern JS natively; no "transpile for old Node" needed).
For 2026 Node services: just run the source.
node --experimental-strip-types --env-file=.env server.ts. No build, no bundle, no source maps, no problem.When You Still Bundle for Node
- Single-executable apps (SEA) — you do want to bundle into one file as the SEA input. esbuild or bun build are good for this.
- Deploying to FaaS (AWS Lambda, Vercel Functions) — the deploy target has a cold-start penalty for large directories; bundling reduces it. Some frameworks (Next.js) do this internally.
- Distributing a CLI as a single file — your users do
npx your-cli, they get one bundled file from npm, instead of pulling your whole transitive tree. - Tree-shaking heavy libraries — when only 20% of
lodashis used, a bundler can keep only the imports you touched. Modern Node doesn't tree-shake from local disk.
If none of those apply, you probably don't need a bundler. Run the source. Save the build time.
Frontend Is Different — Don't Skip Bundling There
For browser code, bundling stays alive — but the tooling is faster. Vite serves dev unbundled (using native ESM in the browser plus on-the-fly transformation), but produces a bundled build for production. esbuild and swc handle the transpile-then-bundle in seconds where webpack took minutes. The 2026 frontend stack: Vite for dev, Vite-or-equivalent for production build, esbuild/swc as the underlying compiler.
The Node + Frontend Monorepo Setup
A common 2026 layout:
apps/web— frontend, uses Vite/Next.js, bundles for production.apps/api— Node backend, runs source directly withnode --experimental-strip-types, no bundle.packages/shared— TypeScript utilities used by both, referenced viaworkspace:, type-checked but otherwise not built.
The frontend has a build step because the browser needs one. The backend doesn't. The shared package needs neither. Each surface uses what fits, no "build the world" tax.