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

Stefano Magni
JavaScript in Plain English
4 min readMay 26, 2021

--

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.

This article is about a React and TypeScript project migrated from Webpack to Vite and ESBuild.

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.

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.

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.

Hi! I’m Stefano Magni, I’m a passionate Front-end Engineer, a speaker, and an instructor. I work remotely as a Senior Front-end Engineer / Team Leader for WorkWave.

I love creating high-quality products, testing and automating everything, learning and sharing my knowledge, helping people, speaking at conferences, and facing new challenges.

You can find me on Twitter, GitHub, LinkedIn. You can find all my recent contributions/talks etc. on my GitHub summary.

More content at plainenglish.io

--

--

I’m a passionate, positive-minded Senior Front-end Engineer and Team Leader, a speaker, and an instructor. Working remotely since 2018.