How JavaScript works: A deep dive into Vite

Lawrence Eagles
SessionStack Blog
Published in
10 min readMay 4, 2022

--

This is post # 61 of the series, dedicated to exploring JavaScript and its building components. In the process of identifying and describing the core elements, we also share some rules of thumb we use when building SessionStack, a JavaScript tool for developers to identify, visualize, and reproduce web app bugs through pixel-perfect session replay.

Introduction

Vite is a JavaScript build tool created by Evan You, the creator of Vue. And Vite simplifies the way we build and develop front-end applications. At its core, Vite primarily does two things:

  1. Serve your code locally during development
  2. Bundle your code and assets for production.

But these are primarily what other JavaScript bundlers like Webpack, Parcel, and Rollup do. So why Vite?

The problem is that before now, the JavaScript language did not have a standard module system, so web developers did not have a native way to split JavaScript codes into modules that can be exported and imported when needed. And this led to the development of different non-standard module systems for JavaScript such as CommonJS — CJS and Asynchronous module definition — AMD. And tools such as Webpack that supports these module systems, and concatenates multiple javascript files and assets into a single bundle were developed.

But while Webpack is great and works well, the build process becomes increasingly slow as the app adds more code and dependencies.

However, with the addition of ES module — ESM to JavaScript in 2015, the JavaScript language now has a standardized module system that runs natively in the browser. And by 2020 ES modules are almost universally supported by all browsers.

Vite uses native ESM to bundle JavaScript files and application assets. And this enables Vite to load codes instantly no matter how large the size of the file might be.

Under the hood, Vite uses Rollup for the production build and features an optimized Rollup configuration out of the box. Also, Vite uses esbuild for dependency pre-bundling. And this leads to significant performance improvements.

In a nutshell, Vite is a next-generation JavaScript build tool that leverages modern JavaScript APIs and toolings to simplify and speed up the build process.

Vite is fully-typed, and it ships with a lot of advanced and rich features such as Hot module replacement — HMR, universal plugins support, instant server start, out-of-the-box support for TypeScript, JSX, CSS, and more.

How Vite Works

In this section, we will look at how Vite works internally and how it is different from traditional bundle-based build tools like Webpack, Parcel, and Rollup.

There are two main issues with bundle-based build tools: slow dev-server cold-start and slow updates.

Also, we will learn about these issues and how Vite solves them.

The image below shows the setup of a bundle–based dev-server:

source: https://vitejs.dev/assets/bundler.37740380.png

From the image above, when we code-start the bundle-based dev-server of build tools like Webpack, Parcel, or Rollup, they have to crawl and build our entire application before it can be served on the dev-server. And this process gets increasingly slower as the application files and dependencies grow.

Vite takes a completely different approach which is made possible by leveraging ES modules.

Consider the image below:

source: https://vitejs.dev/assets/esm.3070012d.png

From the image above, we can see that when we code-start a native ES-module-based dev-server like the Vite dev-server, the server starts instantly.

And this is because of the following:

  • Vite pre-bundles the app’s dependencies — that does not change often, by using esbuild.
    esbuild is built with Golang making 10x-100x faster than JavaScript bundlers. And this redounds to the performance of Vite.
  • Vite uses route-based code-splitting to determine what part of the code needs to be loaded. And it does this on the fly; thus it does not have to re-bundle the whole app.
  • Vite servers the code over native Es module. Thus allowing the browser to take over some part of the bundling process in development. And the result of this is that Vite now only transforms and serves source code that is requested by the browser.

The other issue as noted above is slow updates. This is obvious because bundle-based build tools rebuild the entire application on each update. This approach is not optimal because it is expensive, especially for applications with large dependencies, and the update speed decreases linearly as the app size and dependencies increase. Also, reconstructing the page leads to the loss of the current state.

And to address this issue, module bundlers often use Hot module replacement — HMR.

HMR is a way of updating changed modules in a running application without updating the rest of the page.

However, in bundle-based bundlers, the update speed of HMR significantly decreases as the app size grows.

Vite performs HMR over ESM, and when a module is updated, Vite only invalidate the chain between the updated module and its closest HMR boundary.

Consequently, HMR in Vite is consistently fast regardless of the size of the application.

Also, Vite uses the browser to speed up full page reloads by leveraging HTTP headers. And strongly cache dependency module requests are supported via Cache-Control: max-age=31536000,immutable, so they don’t hit the server again.

Lastly, source code module requests are made conditional via 304 Not Modified.

And all these give Vite a significant performance advantage over bundle-based build tools.

While Vite has some clear advantages over bundle-based bundlers like Webpack and Rollup, it is interesting to see how it compares with other ESM-bundle-based bundlers like Snowpack and WSM.

We will learn about this in the next section.

Vite vs Other ESM-bundlers

Compared with other ESM bundlers like Snowpack, Vite still has some advantages. Although there are some differences in the implementation details of Vite and Snowpack both bundlers share a lot in common and enjoy some technical advantages over bundle-based build tools.

However, one of the main differences between these two bundlers is their method of building for production.

Snowpack outputs unbundled files that are transformed into separately built modules and allows the developer to feed them into any bundler of choice e.g Rollup, Webpack, or esbuild. While Vite opts for deeper integration with the Rollup bundler for the production build. And this enables Vite to support a universal API, and several other features out of the box, such as:

WMR is another ESM-bundler that provides a similar feature set as Vite. But it is built by the Preact team for Preact. So if you are working with Preact is probably the best choice.

In the next section, we will learn how to work with Vite by setting up a Vite project and building a simple app.

Setting Up a Vite Project

Vite is used to scaffold a wide range of frontend applications as it supports Vue, React, Svelte, Preact, Vanilla JavaScript, and more. But since Vite is created by Evan You, the creator of Vue, Vite provides first-class Vue support.

To scaffold a project simply open your terminal and run:

npm create vite@latest

Choose a project name and select a template as seen below:

Then follow the on-screen instruction to complete the setup.

Note: you can also select your template by using the — template flag in the CLI as seen below:

And doing this would skip the step shown in the image above.

After selecting a template, run: npm install to install the needed dependencies.

And run: npm run dev to start the dev-server. Now you get:

The app is a simple counter app. But we can improve on it. In the src directory, create a components directory and create a Counter.jsx file in it. Add the following code to the Counter.jsx file:

The Counter component above is styled using a combination of CSS module and SCSS. And this is easy because Vite provides built-in support for both. Let’s create the SCSS file. In the components directory, create a counter.module.scss file with the following code:

Now, install SASS by running: npm install -D sass.

Once this is done, we need to import and use the Counter component. And to do this, update the App.js file by replacing the code with the following:

Now you get:

Notice the app’s view updated itself because of Vite’s HMR.

Note Vite provides built-in support for CSS modules and pre-processors such as SASS, LESS, and Stylus.

Vite treats any file ending in .module.css as a CSS module. Consequently, importing such a file will import the module object.

In the small contrived app above, we have combined these features to style the counter component.

Conclusion

Vite is a French word that means fast. And Vite is blazing fast indeed.

Vite is one of the next-generation JavaScript bundlers aimed to simplify and speed up development and the build process.

In this article, we have learned a lot about Vite. And I hope you will give it a try in your next front-end project.

ESM bundlers like Vite make it much easier for software to have efficient and high-performing code. And since we all like to apply new technologies & upgrade our code so even if we feel we’ve tested everything before release, it’s always necessary to verify that our users have a great experience with our product.

A solution like SessionStack allows us to replay customer journeys as videos, showing us how our customers actually experience our product. We can quickly determine whether our product is performing according to their expectations or not. In case we see that something is wrong, we can explore all of the technical details from the user’s browser such as the network, debug information, and everything about their environment so that we can easily understand the problem and resolve it. We can co-browse with users, segment them based on their behavior, analyze user journeys, and unlock new growth opportunities for our applications.

There is a free trial if you’d like to give SessionStack a try.

SessionStack replaying a session

If you missed the previous chapters of the series, you can find them here:

--

--