Why Turbopack?

When we set out to create Turbopack, we wanted to solve a problem. We had been working on speed improvements for Next.js. We migrated away from several JS-based tools. Babel, gone. Terser, gone. Our next target was another JS-based tool, webpack.

Replacing it became our goal. But with what?

A new generation of native-speed bundlers were emerging, but after assessing the bundlers on the market, we decided to build our own. Why?

Unified Graph

A large reason why frameworks like Next.js have become so popular is that implementing features like SSR (and now RSC) with the current generation of bundlers is non-trivial. You need to create multiple compilers for each output environment (browser, server, etc), and manage the communication between them so that their bundles end up correctly stitched together.

We wanted to remove this maintenance burden from Next.js and any framework that chooses to use Turbopack. We can also create a cleaner and more stable implementation by designing a single unified graph that can be used to generate bundles for multiple environments.

Bundling vs Native ESM

Frameworks like Vite use a technique where they don’t bundle application source code in development mode. Instead, they rely on the browser’s native ES Modules system. This approach results in incredibly responsive updates since they only have to transform a single file.

We experimented with this approach, but ran into scaling issues with large applications made up of many modules. A flood of cascading network requests in the browser lead to a relatively slow startup time. For the browser, it’s faster if it can receive the code it needs in as few network requests as possible - even on a local server.

That’s why we decided that, like webpack, we wanted Turbopack to bundle the code in the development server. Turbopack can do it much faster, especially for larger applications, because it is written in Rust and skips optimization work that is only necessary for production.

Incremental Computation

There are two ways to make a process faster: do less work or do work in parallel. We knew if we wanted to make the fastest bundler possible, we’d need to pull hard on both levers.

We decided to create a reusable Turbo build engine, similar to Parcel's request manager and rustc's query system, for distributed and incremental behavior. The Turbo engine works like a scheduler for function calls, allowing calls to functions to be parallelized across all available cores.

The Turbo engine also caches the result of all the functions it schedules, meaning it never needs to do the same work twice. Put simply, it does the minimum work at maximum speed.

Lazy bundling

Early versions of Next.js tried to bundle the entire web app in development mode. We quickly realized that this ‘eager’ approach was less than optimal. Modern versions of Next.js bundle only the pages requested by the dev server. For instance, if you go to localhost:3000, it’ll bundle only pages/index.jsx, and the modules it imports.

This more ‘lazy’ approach (only bundling assets when absolutely necessary) is key for a fast dev server. Native ESM handles this without much magic - you request a module, which requests other modules. However, we wanted to build a bundler, for the reasons explained above.

esbuild doesn’t have a concept of ‘lazy’ bundling - it’s all-or-nothing, unless you specifically target only certain entry points.

Turbopack’s development mode builds a minimal graph of your app’s imports and exports based on received requests and only bundles the minimal code necessary. Learn more in the core concepts docs.


We wanted to:

  • Support a unified graph. This allows frameworks to use a single compiler that can target multiple environments.
  • Build a bundler. Bundlers outperform Native ESM when working on large applications.
  • Use incremental computation. The Turbo engine brings this into the core of Turbopack’s architecture - maximizing speed and minimizing work done.
  • Optimize our dev server’s startup time. For that, we build a lazy asset graph to compute only the assets requested.

That’s why we chose to build Turbopack.

On this page