kg.

Is Vite faster than Turbopack?

Kyle Gill portrait

Kyle Gill, Software Engineer, Particl

Last updated

Vite comes from the French word for “quick”, but is it really?

I’ve spent the last 3, almost 4 years building our web app at Particl with Next.js. For the most part, it has been a great, productive experience.

Anecdotally however, we began to experience increasingly painful performance issues with the dev server as our codebase grew. The dev server would report compilation times as I navigated to new pages of 5s, but I’d sit and watch as the browser continued to load for 5 more seconds. Like Jeff Bezos, the anecdotes started to speak louder to me than the data, so I decided to try some real-world tests.

This post compares the Particl React app’s performance in the local development server with the following bundlers:

  • Next.js + Webpack
  • Next.js + Turbopack
  • Vite + Rollup
  • Vite + Rolldown

Note: since Next.js is pretty tied to Webpack and your only choices are Webpack or Turbopack, I sort of refer to it as the bundler, when yes, it does a lot more than bundle code.

What are we measuring?

To make for some productive tests and to appease my previous manager’s voice in my head, I had to decide what I was measuring.

Since this is the app I work on day to day, I figured I would time a couple normal actions I do on the regular. They are:

  1. Cold start: starting the dev server with npm run dev (technically rm -rf node_modules/.vite && npm run dev or rm -rf .next && npm run dev) and without any sort of cache. This action occurs least frequently on the day-to-day basis, but I figured it would set a nice baseline.
  2. Page compilation: navigating to a new page on a separate route.
  3. Hard refresh: refreshing a page with the browser refresh button (which also mimics the behavior of a file save that cannot be React fast refreshed).
  4. Fast Refresh: React Fast Refresh of an edit on a single component, preserving state and the other page contents.

Rather than scientific benchmarks using some fancy CLI tool, I figured I’d just perform the tests the same way I would do at work: just starting up the server and running the code on my machine.

I recorded each test and scrubbed through the frames to calculate how long they took to complete.

Test Setup: the Particl app and my plain jane Macbook

To give you an idea of what we’re working with, I run a stock M1 Macbook Pro from 2021. I’ve run DaisyDisk enough times to try and keep my node_modules folders in check, but no amount of cleanup will ever truly solve my storage problems (maybe switching to pnpm, who knows).

I ran the tests with all my other day to day apps open, like Slack, Cursor, Messages, and Chrome.

I cloned the particl-web repo that houses all of our frontend code twice. Once as particl-web, and once as particl-web-2. I’d open up the relevant branches and fire up 2 servers to compare 2 tools at a time:

  • main has Next.js + Webpack
  • turbo-speed has Next.js + Turbopack
  • vite has Vite + Rollup
  • vite-rolldown has Vite + Rolldown (via the rolldown-vite package, installed with pkg.pr.new)

The Particl app is a medium sized app (200k lines of code, ~750 files, ~100 pages), we use the following technologies:

  • client based routing with next/router and TanStack Router (which uses automatic code splitting)
  • TanStack Query for state management
  • MUI for theming and components
  • ant-design-charts for data vizualization
  • zod for schema validation

In both development and production, it connects to a python API, so no backend JavaScript code is run. That means the Next.js app being tested runs the Pages Router.

Results

TL:DR - Next.js w/ Webpack is slow always, Turbopack has an edge on Hard Refresh, but Vite and Rolldown fly when it comes to navigating between pages.

Here’s a summary of the tests:

overall results

Because I planned to move to Vite, I decided to pit each tool against Vite side-by-side. Looking back, maybe I should have just done them each separately, but I think it can be interesting to watch both tools chug next to each other. Also I’m not gonna go record all these experiments again, sorry.

The following has a recording of each test, with Vite always on the right side of each recording:

Test #1: Cold start

Cold start

Cold starts were measured from hitting enter in the terminal to the full application UI rendering for its first frame.

BundlerTime (seconds)
Next.js + Webpack41.6
Next.js + Turbopack21.2
Vite + Rollup11.7
Vite + Rolldown9.9

Next.js vs Vite

Turbopack vs Vite

Rolldown vs Vite

Test #2: Page compilation

Page compilation

Page compilation is measured from the moment a link is clicked to the moment the page starts rendering (no longer a blank white screen).

BundlerTime (seconds)
Next.js + Webpack13.1
Next.js + Turbopack8.8
Vite + Rollup0.7
Vite + Rolldown0.5

Next.js vs Vite

Turbopack vs Vite

Rolldown vs Vite

Test #3: Hard refresh

Hard refresh

Hard refresh is measured from the moment the browser refresh button is clicked to the moment the page starts rendering.

BundlerTime (seconds)
Next.js + Webpack9.6
Next.js + Turbopack0.9
Vite + Rollup2.4
Vite + Rolldown2.0

Next.js vs Vite

Turbopack vs Vite

Rolldown vs Vite

Test #4: Fast refresh

Fast refresh

Fast refresh is measured from the moment a file is saved to the moment the changes are reflected in the browser.

BundlerTime (seconds)
Next.js + Webpack5.5
Next.js + Turbopack1.1
Vite + Rollup2.7
Vite + Rolldown0.7

Next.js vs Vite

Turbopack vs Vite

Rolldown vs Vite

Caveats

I’ve intentionally avoided the word “benchmark” because this is not a super fair assessment.

Our app is a duct-taped mess of dilapidated dependencies, some of which aren’t up to date and probably violate all “best practices”. I suspect many apps are like that, but the exact nature of our app might skew these results some direction I’m not aware of.

This is really just the simplest test I could conceive that would mimic what my day to day would be like, and really emphasizes the differences between tools.

Some notes that should make you squint at these results:

  • Rolldown is not stable, so these tests could very well be different if I ran them again in a week.
  • Turbopack is being actively developed, and I’ve heard from the Turbopack team that it’s most performant with the App Router, which my app isn’t using, meaning it might be faster on an App Router app.
  • I’m just an average joe and probably got some things wrong here, so please forgive me if I did.

Takeaways

  • Next.js + Webpack is always slower than alternatives
  • Turbopack is really great at fast edits, though Vite and Rolldown are faster (in our case) navigating between pages
  • Running a big, nasty app for a bunch of users inevitably means things start to slow down

And to answer the question, is Vite faster than Turbopack? Well, it depends.