What is Vite? Why did we consider it? Is it faster than Webpack? Is it mature enough?
This is part of a three-article series about migrating our React+TypeScript codebase from Webpack to Vite. Part 2 is about how we did it, Part 3 is about post-mortem considerations.
From Webpack’s slowness to Vite
It’s always the same story: you start working on a branch, run yarn start and wait for two minutes. Then you save a file and wait for 20 or 30 seconds before the app gets refreshed. Then you switch multiple times among the branches you’re working on, and you need to relaunch the dev server again. Such a terrible Developer Experience.
We reduced this problem by moving to Vite and ESBuild. Keep on reading.
The WorkWave RouteManager UI team works daily on a 150K LOC (and growing, ~250K LOC is the final size) codebase. Due to the nature of the Product and the technical constraints, there is nothing we can do to split the app into little chunks at the moment. 75% of the code is shared and used by all the app sections.
The app is based on React and TypeScript, spans a Web Worker, uses Webpack, babel-loader, ts-loader, and fork-ts-checker to bundle and validate the code. All the dependencies are updated weekly.
Recently, Vite 2.0 has been released. Its core idea is simple: serving the files “as are” to the browser leveraging ESModules. When the browser parses the source files and asks the webserver for an imported file, Vite does
convert NPM dependencies to ESModules and serve them
transpile your source code through ESBuild
serve the code to the browser
What does it mean? It means that Vite doesn’t bundle the code in advance. Instead, when the browser asks for a file, Vite transforms it. A picture is worth more than a thousand words.
The browser loading the thousands of unbundled .ts and .tsx files.
The files are cached, but Vite essentially removes the burden from the build tool, moving it to the browser. You can read more on Vite docs or on CSS-Tricks’ Comparing the New Generation of Build Tools article.
What about the build? Vite leverages Rollup to build the project, no worrying about browser compatibility of the final bundle.
Vite’s advantages
In contrast to Webpack, Vite is not a generic tool. Vite supports a few sweet spots. If your project falls in these spots, Vite offers
Better performances, thanks to the speed of ESBuild.
Less configuration.
Fewer dependencies: everything required for a React+TypeScript project like ours is managed directly by Vite, React Fast Refresh included.
But not all that glitters is gold! What does Vite not include?
TypeScript validation: to be short, ESBuild removes type annotations without validating them. You must run tsc on your own to validate types.
It depends on your configuration, but in our case, ESLint runs thanks to fork-ts-checker. Vite doesn’t care about ESLint.
Notice: I’m going to talk about these missings in the 3rd part of this series, including some objective considerations about Vite and Webpack and the overall Developer Experience.
Last but not least: are Vite and its ecosystem mature enough?
The ecosystem likes it: for example, Storybook will support it, Cypress has first-class support for Vite.
Vite’s creator, Evan You, is the same as Vue.
We had just one problem with one dependency with Vite, and Evan fixed it in less than two days.
In the end: betting on Vite is not hazardous. Anyway, we decided to keep the codebase compatible with Webpack to swap between Vite and Webpack in case of troubles.
Benchmarks
To give you an idea of the performance improvements, take a look at our early benchmarks, the ones I shared with the rest of the team
Tool | yarn start | app loads in | React component hot reload ** | web-worker change "hot" reload ** |
---|---|---|---|---|
Webpack* | 150s | 6s | 13s | 17s |
Vite* | 6s | 10s | 1s | 13s |
* Early benchmark where Webpack runs both ESLint and TypeScript while Vite doesn't
** Means from CTRL+S on a file to when the app is ready
Then, getting the codebase ESBuild-ready allowed us to put Webpack on a diet too, these are our final benchmarks.
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
Migrating the codebase
The 2nd part of this series deepens the technicalities under the migration of our codebase. The 3rd part is about the conclusions, the DX, and a more fair comparison with Webpack.
Top comments (0)