I took a look inside Vite 8 and the build bundler had been replaced wholesale with Rust
Vite 8 merged esbuild for dev and Rollup for builds into Rust-based Rolldown. The problems two bundlers caused, why builds got several times faster, and why I haven't upgraded yet.
#Vite #Rolldown #Build #Frontend #Rust
My blog's frontend had been stuck on Vite 4 for a long time. It ran fine, so I didn't bother touching it, and before I knew it Vite 8 was out. That's skipping four major versions, so before upgrading I read up on what had changed, and the inside of the build tool had been swapped out wholesale for Rust . In this post I go over what Vite 8 changed, and why builds suddenly got several times faster. At the end I also write down, honestly, what versions my own projects are on right now. Vite originally used two bundlers This is the most important background, so it has to come first. From the start, Vite used two bundlers. esbuild for development, and Rollup for production builds. The reason for splitting it in two is that they were good at different things. esbuild is written in Go and is very fast. So it was used to pre-transform dependencies when starting the dev server. But it was weak on fine-grained control, like how to split chunks or how to shape the output. Rollup, on the other hand, was excellent at that output control but slow. So the work was divided: esbuild for speed in development, Rollup for control in the build. Even now, if you open node_modules in a Vite 4 project, esbuild and rollup sit side by side. The two of them were each working at different points inside Vite. But having two bundlers causes problems Two bundlers means two plugin systems and two subtly different behaviors. This is where things that were fine on the dev server break once you actually run build. Glue code keeps getting added to cover the small differences between the two, and edge cases pile up. The reason "it works in dev but not when I build" was so hard to track down is that two different tools were processing the same code differently in the first place. No matter how long you stared at the code, there was nothing wrong with the code. The problem was on the side of the tools reading it. Vite 8 merged them into Rolldown Vite 8 merged the two into a single bundler, Rolldown . Rolldown is a new bundler written in Rust, and it stays compatible with Rollup's plugin API. So the same bundler handles both development and the build. The room for dev and prod to behave differently is gone altogether. People call it the biggest architectural change since Vite 2, and going by the migration docs that's no exaggeration. The config file side, though, is surprisingly quiet. The build.rollupOptions key still works as is. The name says rollup but what actually runs is Rolldown, so it looks like there's almost no new configuration to learn when moving over. // vite.config.ts // Vite 8 still uses this key name as is. What runs inside is Rolldown, not Rollup. export default defineConfig({ build: { rollupOptions: { output: { manualChunks(id) { if (id.includes('node_modules/react')) return 'react-core'; }, }, }, }, }); So why did it get faster? By multiples, not percent This was what I was most curious about. There isn't one reason for the speedup. Several are stacked together. First, it runs as native Rust . JavaScript is single-threaded and has GC (garbage collection) pauses. Rust has no GC and can do real multi-threaded parallelism. Bundling is work that handles thousands of files at once, so whether it can run in parallel or not is decisive. Second, the whole pipeline runs in one language . Parsing, building the dependency graph, optimization and code generation, every stage finishes inside Rust. There's no stretch where it stops to pass data back and forth with JavaScript. Before, the result esbuild had transformed was received in JavaScript and then handed to Rollup, so there was a cost at each of those boundaries. Third, Oxc sits at the bottom . Underneath Rolldown is a Rust parser called Oxc. It's said to be dozens of times faster than Prettier at code formatting, and since the speed is different starting from parsing, the bundling built on top of it gets faster too. So the improvement comes out at 10 to 30 times, not 10 to 30 percent. Linear, for one, reportedly announced that its build went from 46 seconds to 6 seconds, but that's not a number I verified myself, so I'm only noting it as something I've heard. What does seem clear is that when you change the language, the improvement shows up in multiples, not percent. What gets in the way of upgrading It's a jump of four majors, so it isn't free. Following the migration docs, a few changed config options need fixing, and the Node version has to be brought up to a recent one too. This server is still on Node 18, so that's the first obstacle. That said, Rolldown is compatible with the Rollup plugin API, so most plugins you were using are said to work as they are. The only one I use is the react plugin, so I don't expect to get stuck there. One thing I liked is that Vite, Rolldown and Oxc now move together like one team. Oxc does the parsing, Rolldown the bundling and Vite the build as a whole, and since all three are tools from the same camp, there's less chance of behavior going out of step between stages. And after all that, I didn't upgrade Having read this far you'd want to upgrade right away, but I actually haven't. I checked the versions of my projects. Below are the values I read directly from each project's package.json as of September 2026, when I'm revising this post. coin-server/coinSite vite ^6.4.2 ieum-server/ieumSite vite ^5.4.11 travel-server/travel-frontend vite ^5.4.9 monitor-server/monitor-client vite ^5.0.0 blog-server/blog vite ^4.1.0 - the blog this post is on portfolio-server/final-portfolio vite ^4.1.0 couple-server/... vite ^4.1.0 game-server/... vite ^4.1.0 taro-server/... vite ^4.1.0 Out of nine, not one is on 8. The highest is the crypto site on 6, and the very blog this post is on is stuck on 4. I wrote that you should upgrade to 8 and didn't do it myself. The blog runs fine, so it got pushed down the priority list. A build that's a few seconds slower is something I run into once or twice a day, and I don't know what will break if I skip four major versions. On top of that, this blog has things like its manualChunks rules and the CJS helper chunk split tuned by hand, so if the bundler changes wholesale I'd have to measure all of that again. I did set one rule, though. The next time the blog needs major work, I'll upgrade along with it. Upgrading only the tool version as a separate task has too much to check for what you get out of it. For a project that's just starting, it makes sense to start on 8 without thinking twice, and for a project that's already running, I'd recommend upgrading while you're in there for other work.