Vite-Next Generation Frontend Tool


Vite (French word for “quick”, pronounced /vit/, like “veet”) is a build tool that aims to provide a faster and leaner development experience for modern web projects. 


It consists of two major parts: 


Vite is opinionated and comes with sensible defaults out of the box, but is also highly extensible via its Plugin API and JavaScript API with full typing support.


Why Vite

Slow Server Start

Vite improves the dev server start time by first dividing the modules in an application into two categories: dependencies and source code.


Dependencies: Vite pre-bundles dependencies using esbuild.


Source code: Not all source code needs to be loaded at the same time (e.g. with route-based code-splitting).


Vite only needs to transform and serve source code on demand, as the browser requests it. Code behind conditional dynamic imports is only processed if actually used on the current screen.





Slow Updates

When a file is edited in a bundler-based build setup, it is inefficient to rebuild the whole bundle for obvious reasons: the update speed will degrade linearly with the size of the app.


In Vite, HMR is performed over native ESM. When a file is edited, Vite only needs to precisely invalidate the chain between the edited module and its closest HMR boundary (most of the time only the module itself), making HMR updates consistently fast regardless of the size of your application.


Vite also leverages HTTP headers to speed up full page reloads. Source code module requests are made conditional via 304 Not Modified, and dependency module requests are strongly cached via Cache-Control: max-age=31536000,immutable so they don’t hit the server again once cached.



Why Bundle for Production

To get the optimal loading performance in production, it is still better to bundle your code with tree-shaking, lazy-loading and common chunk splitting (for better caching).


Ensuring optimal output and behavioral consistency between the dev server and the production build isn’t easy. This is why Vite ships with a pre-configured build command that bakes in many performance optimizations out of the box.


Vite opts to have a deeper integration with one single bundler (Rollup) in order to provide a more streamlined experience. It also allows Vite to support a Universal Plugin API that works for both dev and build.


Due to a more integrated build process, Vite supports a wide range of features that are currently not available in other build optimizers (Snowpack):



Vite provides many enhancements over native ESM imports to support various features that are typically seen in bundler-based setups.



NPM Dependency Resolving and Pre-Bundling


Native ES imports do not support bare module imports like the following:


import { someMethod } from ‘my-dep’


The above will throw an error in the browser. Vite will detect such bare module imports in all served source files and perform the following:

  1. Pre-bundle them to improve page loading speed and convert CommonJS / UMD modules to ESM. The pre-bundling step is performed with esbuild and makes Vite’s cold start time significantly faster than any JavaScript-based bundler.
  2. Rewrite the imports to valid URLs like /node_modules/.vite/my-dep.js?v=f3sf2ebd so that the browser can import them properly.



Hot Module Replacement

Vite provides an HMR API over native ESM. Frameworks with HMR capabilities can leverage the API to provide instant, precise updates without reloading the page or blowing away application state.




Vite supports importing .ts files out of the box.


Vite uses esbuild to transpile TypeScript into JavaScript which is about 20~30x faster than vanilla tsc, and HMR updates can reflect in the browser in under 50ms.



First Class Vue Support

Vite was initially created to serve as the future foundation of Vue.js tooling. The official Vue plugin still provides first-class support for Vue’s Single File Component format, covering all advanced features such as template asset reference resolving, <script setup>, <style module>, custom blocks and more. In addition, Vite provides fine-grained HMR for Vue SFCs. For example, updating the <template> or <style> of an SFC will perform hot updates without resetting its state.




.jsx and .tsx files are also supported out of the box. JSX transpilation is also handled via esbuild, and defaults to the React 16 flavor. React 17 style JSX support in esbuild is tracked here.



Faster Dependency Pre-Bundling

Vite uses esbuild instead of Rollup for dependency pre-bundling. This results in significant performance improvements in terms of old server start and re-bundling on dependency invalidations.



Monorepo Support

Vite is designed to handle monorepo setups and we have users successfully using it with Yarn, Yarn 2, and PNPM based monorepos.




Importing .css files will inject its content to the page via a <style> tag with HMR support. You can also retrieve the processed CSS as a string as the module’s default export.




If the project contains valid PostCSS config (any format supported by postcss-load-config, e.g. postcss.config.js), it will be automatically applied to all imported CSS.



CSS Modules

Any CSS file ending with .module.css is considered a CSS modules file. Importing such a file will return the corresponding module object:



CSS Pre-processors

Vite does provide built-in support for .scss, .sass, .less, .styl and .stylus files. 



Static Assets

Importing a static asset will return the resolved public URL when it is served:




Pre-compiled .wasm files can be directly imported – the default export will be an initialization function that returns a Promise of the exports object of the wasm instance:



Web Workers

A web worker script can be directly imported by appending ?worker or ?sharedworker to the import request. The default export will be a custom worker constructor:



Async Chunk Loading Optimization

In real world applications, Rollup often generates “common” chunks – code that is shared between two or more other chunks. Combined with dynamic imports, it is quite common to have the following scenario:




In the non-optimized scenarios, when async chunk A is imported, the browser will have to request and parse A before it can figure out that it also needs the common chunk C. This results in an extra network roundtrip:


Entry —> A —> C


Vite automatically rewrites code-split dynamic import calls with a preload step so that when A is requested, C is fetched in parallel:


Entry —> (A + C)


It is possible for C to have further imports, which will result in even more roundtrips in the un-optimized scenario. Vite’s optimization will trace all the direct imports to completely eliminate the roundtrips regardless of import depth.