Our Journey With Vite and Why We Turned Back to Webpack

Vite 2 promises a lightning-fast developer experience. After jumping the opportunity we faced some major problems and had to get creative

Lukas Gamper
Better Programming

--

Photo by Robynne Hu on Unsplash

For many years we used Webpack with the typescript compiler tsc to bundle our application. Starting the dev server took pretty long and the hot module replacement needed so long to update the browser, that it was really hard to keep focused. Many times we switched to checking the news ticker or social media while waiting for the browser to render the changes.

Vite 2 promised a lightning-fast developer experience and in March 2021 it finally became stable. We had to jump at the opportunity. This was the tool, to bring our developer experience to the next level. So, the decision was made, setting up the Vite development environment turned out quite easy.

This is our journey with Vite and the major problem that pushed us back to use Webpack again.

The Stellar Performance of Vite

Vite delivered, what it promised. To start the dev server it takes half a second! The hot module replacement was more or less instantaneous. This was what we had hoped for!

A bit disappointing was the page reload. It took about 4 seconds, mainly because of the sheer size of the application. The main product of our company is a CRM for clubs and associations with a huge frontend composed of 1'300 files hosting 160'000 lines of typescript and vue 2 template code. So it’s not surprising, the browser needs some time to load 1'300 modules. But over all, the developer experience had improved a lot.

After using Vite for some time, two pain points got more severe over time.

1. No Type Checking with Vite Dev Server

Type checking is one of the major benefits of TypeScript. While coding most errors are discovered by type checking. This saves a lot of time and prevents a lot of frustration. If the code passes the type checking only the logic errors are left. All the syntactic errors are found during type checking.

Vite uses esbuild under the hood to compile typescript to javascript. Esbuild is lighting fast, but it ignores all type information. This means we lose the major benefit of typescript. There exist a type-checking tool for Vite — vue-tsc — but it has no watch mode. This makes it useless in the dev server.

Our product is compiled on the CI, so we hardly ever compile it locally. It happened regularly, that the code run on the local dev server without any errors, but it failed on the CI. Since the CI takes a bit less than an hour to complete, it felt even more painfully than the old Webpack solution. After working on a new feature for an hour, we had to go back and fix some minor type errors, discovered on the CI.

2. Typescript Interfaces Become Empty Files with Esbuild

We used the common default import for typescript interfaces like everybody does:

import IExportName from '@/path/to/IExportName'

If the module consists only of an interface, Vite fails to run the application. This is because esbuild ignores all type information and the file compiles to an empty module, which cannot be imported. There exists a solution

import type IExportName from '@/path/to/IExportName'

But this means all interface imports had to be changed. In addition the IDE generates normal imports on auto import. This was quite unpleasant because every auto-import had to be corrected manually.

Use the Best of Both Worlds

Now we had the choice between Skylla and Charybdis. Should we use the slow Webpack setup or go for the fast Vite without type checking?

During a long night, a brilliant idea came up: If Vite achieves the lightning-fast developer experience by using esbuild, why couldn’t we use esbuild in Webpack?

A short short research was enough: there exists a Webpack loader for esbuild — esbuild-loader! We digged out our Webpack config file and used the esbuild-loader to compile and minify the files. This was faster but we lost type checking since esbuild does ignore the types.

The solution was to use the fork-ts-checker-webpack-plugin. This plugin spans a separate process where it runs the typescript compiler to check for type errors. Since it runs the type checking in a separate process, it does not slow down the dev server.

The important part of the Webpack config is quite simple:

As a result, the Webpack dev server starts in 12 seconds and the page reloads needs 4 seconds. The hot module replacement updates the browser in 2 to 4 seconds.

This is not as fast as the Vite setup but is much faster than our original Webpack setup.

Conclusion

Our journey to Vite gave us a fast developer experience but of the cost of reduced type checking. For us, the lightning-fast dev server did not compensate for the lack of continuous type checking.

The integration of esbuild in our Webpack setup allowed us to keep the safety net of type checking while having a fast enough developer experience to get distracted by the compile time of the dev server.

What are your experiences?

Do you have experiences with Vite and typescript? I’m looking forward to hearing your lessons learned from Vite. How do you deal with the type safety during development?

--

--