Vite.js: An awesome tool for TypeScript-based javascript development.

Vite.js: An awesome tool for TypeScript-based javascript development.

Slowness is a thing of the past: The Vite.js build tool has taken a firm place in the Javascript ecosystem and continues its rapid evolution towards TypeScript.

Hardly any programming language evokes as many polarized opinions as JavaScript. While for some developers it's the language of choice, for others the mere sound of it makes their hair stand on end. But that's where Vite - a new project from Evan Yu's team, the founder of the Vue JavaScript framework - comes in, proving that JavaScript can be developed very quickly.

According to the development team, Vite (from the French "vite" - fast) is designed to make a name for itself in the JavaScript ecosystem, first and foremost by making development fast and easy. As a development server and build tool, Vite guides JavaScript developers from project creation to release. Until now, most developers have relied on webpack - either consciously or through tools like Create React App or Vue CLI (Command Line Interface). But the larger the scale of the project, the slower the webpack development server becomes. Developers wait longer and longer for the changes they make to be displayed in the browser. The accumulated irritation spilled out into the idea of creating Vite. The release of stable version 2.0 in mid-February 2021 further strengthened Vite's position. With the release of version 3, the authors came up with a huge list of Vite-based projects.

Webpack challenges

Webpack is essentially a so-called bundler. It collects all the JavaScript, CSS and image files together and combines them into a much smaller number of separate parts. If, for example, the helper methods are in a different file and the API call is in a different file, they may end up in one long JavaScript file in the finished build. The advantage of this approach is reduced load time for the end user: instead of thousands of files, the browser loads only a few. However, the runtime of a package depends on the number of files.

When building, a few seconds is still relatively tolerable. This becomes problematic when developing on a development server, since webpack bundling is also used here. If developers change a single file, webpack has to re-generate entire packages from dozens of files. Therefore, the so-called hot-swapping of modules, i.e. immediately replacing changed components in the browser without rebooting, quickly loses its edge when the waiting time passes ten seconds. Even Vite takes only 430 milliseconds to launch a bare-metal React app, while Create React App or webpack takes more than 12 seconds.

By JavaScript standards, webpack is a true dinosaur. Since its first release in 2012, it has matured and is unrivaled, handling the most extreme cases well. For example, so-called "deep imports" are often the cause of errors in the GitHub repository, while webpack rarely has problems in such scenarios. But also the size of the webpack configuration shows flexibility and at the same time complexity, so often about 90% of the usage scenarios lose in speed and usability.

Everything points to speed

Essentially, Vite is designed to do the same thing that webpack does (namely, develop JavaScript projects with productive builds). However, it adheres to a different philosophy. Unlike many end users, developers use modern browsers, and Vite's included development server takes advantage of this. Thus, ECMAScript modules can be directly integrated via the <script type="module"> tag, and any modern browser with dynamic import support can load, interpret, and execute them. The browser converts each import in the JavaScript source code into an HTTP request, which then goes directly to the development server. With the --debug flag, Vite outputs an accurate log that shows, among other things, the resolution (vite:resolve) of HTTP requests:

vite:resolve 0ms   react -> C:/dev/vite-example/node_modules/.vite/react.js?v=f9c662d4&es-interop +800ms

vite:resolve 0ms   react-dom -> C:/dev/vite-example/node_modules/.vite/react-dom.js?v=f9c662d4&es-interop +9ms

vite:resolve 1ms   ./index.css -> C:/dev/vite-example/src/index.css +3ms

vite:resolve 1ms   ./App -> C:/dev/vite-example/src/App.jsx +2ms

vite:resolve 0ms   /src/App.jsx -> C:/dev/vite-example/src/App.jsx +1ms

vite:load 7ms   [fs] /node_modules/.vite/react.js?v=f9c662d4 +782ms

vite:resolve 0ms   ./logo.svg -> C:/dev/vite-example/src/logo.svg +117ms

vite:resolve 0ms   ./App.css -> C:/dev/vite-example/src/App.css +1ms

If the browser requests each file separately, it will result in a speed degradation even if the number of files increases. To avoid this, Vite has the ability to define independent endpoints and thus practice code separation. For example, if a JavaScript module appears on a subpage, it is also only required when entering that subpage - only when necessary does Vite process the module and send it to the browser. This saves time primarily because modules are parsed and compiled by Vite on demand, rather than being built in advance as in webpack:

Name Path Protocol Size Time
localhost / http/1.1 145 B 12 ms
client /@vite/client http/1.1 17.2 kB 11 ms
main.jsx /src/main.jsx http/1.1 1.6 kB 7 ms
react.js?v=2a1b6b4a /node_modules/.vite/react.js http/1.1 850 B 9 ms
react-dom.js?v=2a1b6b4a /node_modules/.vite/react-dom.js http/1.1 2.4 MB 105 ms
index.css /src/index.css http/1.1 1.1 kB 63 ms
App.jsx /src/App.jsx http/1.1 6.5 kB 70 ms
localhost / http/1.1 0 B 3 ms

 

Another problem is the waterfall scenario: with each requested file, in the worst case, many additional modules are added that the browser has to request. Even if it responds to these requests almost instantaneously, the overall HTTP overhead results in time wastage in particular (see the list above). In addition, on the browser side, the number of requests that can be executed is limited. Smart optimization, such as the code splitting mentioned earlier, avoids this by using browser caching and combining dependencies into a single file at server startup. This way, the browser only executes one request per dependency.

Intelligent dependency binding

In the JavaScript world, ECMAScript modules are not the only way to link files. Alternatively, there are methods such as synchronous CommonJS (via require(...) and module.exports), whose use is limited to the JavaScript backend, or the so-called Universal Module Definition, which is meant to unify the other methods and works in both the browser and the backend. However, due to standardization by the ECMA committee, ECMAScript modules are considered future-proof. Nevertheless, to ensure the compatibility of dependencies of any kind in the Vite project, JavaScript developers must adapt and optimize them. In order to save time, Vite only performs adjustments for a modified package.json or lock file.

Thus, not only all dependencies that do not export ECMAScript modules are optimized, but also those whose entry points have import statements to deeper submodules or other dependencies. For example, during Vite optimization, all Lodash JavaScript files - collections of utilities with many functions, each in its own submodule - are merged into a single file for development. At build time, the code is separated accordingly: Only those Lodash submodules that are actually used get compiled.

Easy file optimizations

The Vite development server does not provide the project files as they are on the hard disk when requested. This is because it is necessary not only to handle some boundary cases that are not yet supported by ECMAScript modules, but also to make it possible for plugins to modify the files. One example of such a plugin is TypeScript support: if the browser requests a .ts or .tsx file, it is compiled into JavaScript and returned. It's worth noting that Vite uses esbuild to translate TypeScript into JavaScript. As one of the fastest JavaScript compilers and transpilers, this tool is able to compile TypeScript twenty to thirty times faster than the official tsc compiler, but at the expense of some more exotic language features (see the figure to the post). These are sometimes misinterpreted at build time and cause errors. However, Esbuild describes how to configure the tsconfig file to avoid this. In addition, Vite provides this configuration directly in its TypeScript templates.

In addition, the dependencies in the import instructions are not supported by browsers. This is because neither the absolute nor relative path to the file is specified after import, only the package name. This is also optimized here so that the path is browser-readable:

import { helloWorld } from '/node_modules/dependency-a/dist/dependency-a.js?v=1.2.1'

In addition, Vite already offers many other features such as JSX (JavaScript XML) support, integration of numerous CSS processors such as SASS or PostCSS, and the ability to use WebAssembly modules. In addition to official extensions for Vue or React, an ever-growing number of plugins from the community provide ready-made additional features.

Even websites built on traditional backends such as Laravel, Ruby on Rails or Django often utilize dynamic content using JavaScript components in addition to server-side page rendering. This is also where Vite can improve the development process.

A separate chapter in the documentation explains how, with a few configuration steps, Vite can be used as a development server for the frontend. Basically, these steps can be reduced to setting up the entry point and properly integrating Vite and the JavaScript entry point into the HTML template:

@if (__DEV__)

<!-- Development -->

<script type="module" src="http://localhost:5173/@vite/client"></script>

<script type="module" src="http://localhost:5173/index.js"></script>

@else

<!-- Produktion -->

<script type="module" src="dist/{{ $manifest['index.js']['file'] }}"></script>

<link href="dist/{{ $manifest['index.css']['file'] }}" rel="stylesheet" />

@endif

In development, all JavaScript and CSS references point to a running Vite server (e.g., localhost:5173), while in a production environment they point to static files in the server directory (e.g., ./public/assets).

HMR function

In the JavaScript world, the Hot Module Replacement (HMR) feature has become one of the most valuable features. Once a change is saved, it becomes visible in the browser within seconds - at best. Bundling with webpack ensures that with a large number of files, "immediately" often turns into a few seconds. Vite shows that this is possible in another way. Here, HMR performance is independent of the project size.

When optimizing and processing files, Vite creates a slender dependency graph. This way, the development server knows exactly which file in turn uses others. When any file is modified, Vite traverses its graph starting from that file and ending at the entry point. It checks if the files have the hot attribute in their import.meta metadata and implements Vite's own HMR interface there. If so, it notifies the user that the file has changed, which leads to self-executing the interface code and handling the file change.

If during the traversal process Vite reaches an entry point and does not find such an interface, it simply reloads the entire page in the browser. However, this is a rare case because the import.meta.hot interface is not a new invention. On the contrary, webpack uses an equivalent solution using module.hot, with the only difference being that the webpack developers did not rely on import.meta, which is specific to ECMAScript modules. Thus, HMR support for Vite is already present in many frameworks.

Development and builds with Rollup configuration

Rollup, a modular alternative to webpack that Evan You believes is more promising and therefore better suited as a foundation for Vite than webpack, is used to create productive builds. Vite not only supports many existing Rollup plugins, but can offer deeper integration with them by selecting a specific build tool. Vite's predefined configuration means that most use cases are already solved without additional customization. Those who require a more complex build process, however, can customize all configurations to suit their own requirements and needs. This is because in the broad JavaScript ecosystem, a lot of time is often lost in customizing a project. Everyone would like to write code rather than deal with customizing the environment.

A technically similar tool is Snowpack, a buildable development server also based on ECMAScript modules. Despite all the similarities, there are some fundamental differences. Because of the freedom of choice in Snowpack and the concept of the narrowest possible standard configuration, developers have to, for example, specially configure the bundling for productive builds. For most users, this is important. In addition, Vite Rollup is more deeply integrated as a fixed build tool and thus offers more options.

Diverse build capabilities

The build process is not just an integration with Rollup. Vite includes a number of other features that make building even more convenient. For example, CSS code is broken into chunks - similar to JavaScript code - which allows you to automatically split code. Together with Vite-generated <rel="modulepreload" /> links, this noticeably increases the speed of the finished web application. In addition, the build process optimizes the dependency chains of asynchronously loaded JavaScript code and thus prevents cascading network requests.

In addition, Vite automatically includes a polyfill for dynamically importing ECMAScript modules to ensure compatibility with older browsers. However, other polyfills are not utilized and users must embed them themselves as needed. In addition to creating regular web pages, the assembly provides support for web pages with multiple entry points and libraries. Standard features such as environment variables are also available.

Premature release of Vite 1

In December 2020, You published a statement on the Vite repository about what it considers to be bugs in the development of Vite 1 and what its plans are for the future of Vite. For example, the plugin architecture was much less modular than planned, some Vue features were fixed (instead of modular), and many interfaces lacked selectivity. He proposed some drastic changes, but they conflicted with the ecosystem that had already formed around the first version of Vite. For this reason, he labeled the state as "1.0 Release Candidate," stopped working on Vite 1, and continued working on Vite 2 with his team. On Twitter You, meanwhile, announced that Vite 1 is outdated and developers should move to version 2.

It now appears that the changes he requested are being pushed forward as part of the development of version 2.x. The plugin API has been redesigned by the Vite team, removing or outsourcing some specific features. Configuration is now more clearly divided into build servers and development servers, performance is said to have improved, and several minor issues have been fixed. The user feedback received since the release of the Vite 2 beta in January 2021 has obviously strengthened his vision for the future of Vite.js. Now that the final version is available, it will also be of interest to those who have been avoiding beta versions.

Significance for the JavaScript community

The changes made in Vite 2 could make the tool a real acquisition for the JavaScript world. Already, a few weeks after the first beta was released, new plugins and projects are regularly appearing in the community. Besides the integration of Vite into Ruby-on-Rails projects, there are also less exotic offerings in the form of various starter templates, sample projects or small useful plugins such as automatic image compression. This growth is indicative of the mood of the community, which is also responding positively on social media. Striving for independence from frameworks, React and Svelte developers are also mastering Vite. This is evidenced not only by some issues in the GitHub repository, but also by the wave of tutorials and guides that now flood the Internet (e.g. on the online publishing platform Medium).

Vite 3 speeds up development even more

In version 3, the speed gains are even more noticeable and seem to be contributing to the tool's maturation. An obvious trend in the JavaScript world is speed. This is not only noticeable in Vite, but also in other projects, such as the alternative, much faster Bun compiler, which has already attracted lively attention on social media.

The next goal is on its way

The next stage of Vite's development is to finally support server-side rendering. After the initial hype around frontend frameworks like React or Vue, the growing popularity of server-side rendering is a step towards improving the performance of JavaScript websites. Client-side frameworks, in particular, put a heavy load on initial load times, which, among other things, leads to worse search engine rankings.

Beta 50, the first official implementation of this feature, was published at the end of January. While there are already examples of server-side rendering using Vite in the community, You aims to create a complete solution that should stay true to its core goal of speed by skillfully leveraging existing architecture and features. The current implementation is still experimental, so the official documentation asks for caution and hints at possible changes. However, there are already fully functional examples of projects based on Vue 3 or React.

The non-triviality of the theme makes it a frequent challenge, so Vite has the potential to be a real lifesaver here. However, the entire feature set is not only aimed at convenience and simplification, but also allows you to create applications that would be impossible within a webpack. For example, using the VitePress example, the team impressively demonstrates how the power of Vite can be used in practice and offers ideas of possible uses for the tool.

VuePress and VitePress

In 2018, the Vue team released the first stable version of VuePress. This tool is a combination of a static page generator (SSG) and a single page application (SPA). In practice, this means that the build process converts all content-filled pages into static HTML files, which then loads JavaScript logic the first time the browser is accessed and turns the web page into a regular single-page application. Judging by the name, this application is based on Vue.js 2, so the tool is particularly popular in the Vue community for blogging or technical documentation. The main advantages of this two-page architecture are better optimization for search engines and fast initial load times, similar to server-side rendering. Using SPA allows for additional benefits, namely responsive navigation and the ability to use dynamic components.

However, since VuePress is also webpack-based, it also has the aforementioned issues inherent in it, such as slow hot-swapping of modules and a clunky development server. Therefore, it seemed obvious to the Vue team to create a sister VuePress based on VitePress. By developing both projects in parallel, problems or missing features that have manifested themselves in VitePress can be consolidated into Vite without bureaucracy to provide additional value to a host of other projects.

The sum of the fundamental differences between Vue and VitePress is small: the second version of Vue becomes the third, Vite replaces the webpack substructure, and more attention is paid to performance. This allows for additional improvements, such as doing away with the so-called "double payload".

Double payload

The problem with statically generated pages with single-page application functionality is that content that the user has already loaded into a static HTML file is often reloaded by JavaScript. This means that a much larger amount of information is accumulated during data transfer between the server and the user, which is especially true in the case of poor network connectivity. To avoid this double load, VitePress takes advantage of one of Vue 3's features: static elements can be placed in the Vue 3 compiler. This means that such elements from the rendering function are written to variables and thus are only created once - no matter how often a page or component is rendered.

VitePress recognizes placed elements at compile time and removes them. When a SPA function is initialized in the frontend, it only affects elements that are directly affected by the change. All static content that cannot be changed dynamically remains unchanged. In this way, VitePress solves the double payload problem and typically achieves file sizes of a few kilobytes - with very little load time. By paying attention to seemingly minor issues, VitePress can gain significant momentum overall and stand out from the competition.

Conclusion

Development tools are gaining ground on the open source scene, and for good reason: those who use JavaScript regularly often notice how much easier their work has become just by switching to a faster tool. This experience greatly increases the popularity of such projects.

The potential of Vite.js is becoming especially evident with projects like VitePress, and could lead to further development of the JavaScript community in the near future - just as other great technologies like React, Electron or TypeScript have already done. The versatility makes this tool attractive to a large portion of JavaScript developers. With its third major release, the tool has already firmly established its place in the Javascript ecosystem. The community around Vite is thriving and could lead to even more new developments in JavaScript in the near future. Vite.js is also part of a long tradition of tools that show that Typescript is the future of Javascript. More and more modern frameworks and libraries are written in Typescript by default. Even with a complete rewrite of existing Javascript projects, for example Vue.js 3 in Typescript seems to be the first choice for a significant portion of developers.

Popular Posts

My most popular posts

Maximum productivity on remote job
Business

Maximum productivity on remote job

I started my own business and intentionally did my best to work from anywhere in the world. Sometimes I sit with my office with a large 27-inch monitor in my apartment in Cheboksary. Sometimes I’m in the office or in some cafe in another city.

Hello! I am Sergey Emelyanov and I am hardworker
Business PHP

Hello! I am Sergey Emelyanov and I am hardworker

I am a programmer. I am an entrepreneur in my heart. I started making money from the age of 11, in the harsh 90s, handing over glassware to a local store and exchanging it for sweets. I earned so much that was enough for various snacks.

Hire Professional CRM developer for $25 per hour

I will make time for your project. Knowledge of Vtiger CRM, SuiteCRM, Laravel, and Vue.js. I offer cooperation options that will help you take advantage of external experience, optimize costs and reduce risks. Full transparency of all stages of work and accounting for time costs. Pay only development working hours after accepting the task. Accept PayPal and Payoneer payment systems. How to hire professional developer? Just fill in the form

Telegram
@sergeyem
Telephone
+4915211100235