DEV Community

Cover image for Migrating a 150K LOC codebase to Vite and ESBuild: is it worthwhile? (part 3/3)
Stefano Magni
Stefano Magni

Posted on • Edited on

Migrating a 150K LOC codebase to Vite and ESBuild: is it worthwhile? (part 3/3)

A fairer comparison between Webpack and Vite, some Vite caveats, and the overall Developer Experience.


This is part of a three-article series about migrating our React+TypeScript codebase from Webpack to Vite. Part 1 is about why we decided to migrate, Part 2 is about how we did it.

Putting Webpack on a diet

As said in the previous articles, Vite is faster than Webpack, but it does fewer things. Earlier in this series, I told that our custom Webpack configuration leverages babel-loader, ts-loader, and fork-ts-checker-webpack-plugin that compiles TypeScript and runs ESLint at the same time. On the other hand, ESBuild (that’s at the core of Vite) doesn’t check types neither runs ESLint.

How fast is Webpack without TypeScript and ESLint? Is it fast enough to outstand Vite? The answer is no, but it gets closer. Keep on reading.

Webpack ESBuild Loader

Now that our codebase is ESBuild-ready, we can use it through Webpack, too. webpack-esbuild-loader it’s the solution (discovered in a discussion on Twitter). By removing fork-ts-checker, TypeScript, and ESLint burden from Webpack, we can run a fairer comparison between Vite and Webpack.

Tool 1st yarn start, app loads in 2nd yarn start, app loads in browser reload (with cache), app loads in React component hot reload ** server-data change "hot" reload **
Webpack
(babel-loader + ts-loader + fork-ts-checker)
185s 182s 7s 10s 18s
Webpack
(esbuild-loader)
56s 52s 7s 10s 16s
Vite 48s 31s * 11s 1s 14s

* Vite has an internal cache that speeds up initial loading
** Means from CTRL+S on a file to when the app is ready

That’s quite interesting, the conclusions are

  • We can boost Webpack through ESBuild loader.

  • Even in this case, Vite is faster. In particular, React Fast Refresh makes a huge difference.

We aren’t interested that much in the build time (we are trying to improve the everyday DX), but for completion’s sake, below you can find the build’s performance.

Tool Build
Webpack
(babel-loader + ts-loader + fork-ts-checker)
170s
Webpack
(esbuild-loader)
42s
Vite* 58s

* Turning off Brotli compression

Vite’s issues

I like Vite, but I don’t demonize Webpack. I care about the DX, not the tool itself. That’s why I try to objectively report the issue we’ve found until now while working with Vite:

  • Save after save, the Devtools’ Source Panel lists the same file multiple times. Not a big deal, but sometimes you choose the wrong one.

The Sources panel of the Chrome DevTools that shows multiple time the same file. The correct one is recognizable because it doesn’t have a querystring parameter.

  • Going back and forth in the browser history loads stale files if the cache is enabled. At the same time, disabling the cache makes Vite slower.

  • Vite moves workload from the bundle to the browser: Vite consumes a fraction of RAM compared to Webpack, but the browser’s job will be more CPU-intensive. The fans testify.

  • After a lot of Hot Reloads, you better reload the whole app.

  • There is a small portion of files that we can’t breakpoint through the Devtools, and we still have to understand why.

  • The development version of the front-end app is significantly slower than the built one.

In the end: Vite or Webpack?

The answer comes from the developers who use them the most: Vite!

Vite’s performances and fluidity win over Webpack. The overall DX is an order of magnitude better, even considering the above issues.

I’m going to remove every Webpack dependency, the configuration, and all the scripts in the future😊 (or, at worst, when a Webpack release requires a lot of frontend-ops work).

That’s all! I hope tracking our journey would be helpful for you too. Feel free to leave comments to share your experience or suggesting more improvements.

What's next

I need to try Webpack's file-system cache again. We discarded it because of an old problem, but things could have changed in the meantime.

Then, I also shared how to get the best of the "old" bundling experience and the new one by enabling Rollup watch-mode inside Vite in my Speed up E2E tests for Vite-based apps article.

Post scriptum

Speaking about ESLint, we won’t run it anymore in watch mode while working. The rationales behind this decision are similar to the motivations behind Vite:

  • VSCode runs ESLint every time you save a file

  • Through lint-staged, staged files pass through ESLint

There is no reason to have ESLint actively running anymore. Let’s remove it from Webpack too. And if you run ESLint in watch mode, remember to turn on its cache.

Top comments (11)

Collapse
 
brunolemos profile image
Bruno Lemos

Hey, great series! Does your webpack config has the react-refresh plugin? I found the 10s vs 1s unexpected, it should be closer if you add something like github.com/pmmmwh/react-refresh-we...

Also, does your project use yarn workspaces? And have you compared Vite with alternatives like Snowpack?

Collapse
 
noriste profile image
Stefano Magni

Does your webpack config has the react-refresh plugin

Yes, it has, I'll double-check if it's configured the right way, thanks 😊

does your project use yarn workspaces

Yes, the only noticable thing is that the dependencies are installedin the top-level node_modules while Vite's cache is stored in the local node_modules.

have you compared Vite with alternatives like Snowpack?

Yes, Vite's advantage is that has batteris included for targeting non-ESModules compatible browsers.

Collapse
 
brunolemos profile image
Bruno Lemos

Got it, thanks! I'll experiment with Vite on my next product.

Collapse
 
klvenky profile image
Venkatesh KL

Wow that's been quite a journey I suppose. Great work.
Cheers 👍

Even I was thinking about doing the migration but slowed down to check vite's compatibility with svg & images. Other reason though was that we're not very heavy on the UI as of now. Also, ours is a hybrid app where express handles the base template & webpack is just a dev server used to pull out the build.
I'll explore how it comes out.

Collapse
 
noriste profile image
Stefano Magni

About svg & images: we haven't any issue until now, looking forward to know your conclusions and use cases 😊

Collapse
 
silvenon profile image
Matija Marohnić

Simply thanks for writing this, now I have a much more realistic picture of whether to migrate and how to do it successfully, instead of trying to go all in at once.

Collapse
 
noriste profile image
Stefano Magni

You're welcome, in case you migrate, in eager to know how you do it, the pitfalls, the differences compared to our use case etc. 😊

Collapse
 
feitian124 profile image
ming

great work, helps a lot, thanks

Collapse
 
noriste profile image
Stefano Magni

Thanks ♥️

Collapse
 
lsycxyj profile image
Light Leung • Edited

What about using Webpack5 with disk cache? Or using disk cahce loader?

Collapse
 
noriste profile image
Stefano Magni

I should have tried it but I ended up removing Webpack at all. The problem is always time: I migrated to Vite during the weekends and I didn't have more time for this topic, that's why I hadn't tried to leverage disk cache and comparing it again with Vite. In the end, our developers felt in love with Vite and we decided to stop using Webpack.