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.
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)
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?
Yes, it has, I'll double-check if it's configured the right way, thanks 😊
Yes, the only noticable thing is that the dependencies are installedin the top-level
node_modules
while Vite's cache is stored in the localnode_modules
.Yes, Vite's advantage is that has batteris included for targeting non-ESModules compatible browsers.
Got it, thanks! I'll experiment with Vite on my next product.
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.
About svg & images: we haven't any issue until now, looking forward to know your conclusions and use cases 😊
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.
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. 😊
great work, helps a lot, thanks
Thanks ♥️
What about using Webpack5 with disk cache? Or using disk cahce loader?
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.