When our browser does not support ES Modules, we use tools like Webpack, Rollup, Parcel to extract, process, and connect our source code, but as our projects become more complex and have more modules, The time it takes us to start a Dev Server is getting longer and longer, and when we’re editing code, saving it, even with the HRM function, it may take a few seconds to reflect on the page. This development experience is very bad, and Vite is designed to solve this development experience problem. In general, Vite has the following advantages:

  • Remove the packing step for a quick cold start
  • Timely module hot update does not slow down the hot update as the number of modules increases
  • Truly compile on demand

Bundle vs Bundleless

To learn about Vite, we’ll first talk about Bundle and Bundleless. These are two different development methods. In the past, we used to use Webpack to package and build our code.

  • HTTP/1.1 browsers have parallel connection restrictions
  • Browsers do not support modular systems (e.g. CommonJS packages do not run directly in browsers)
  • Code dependencies and sequence management

Why start trying not to pack

  • As the project gets bigger, the waiting time for startup and hot updates gets longer and longer
  • HTTP/2.0 multiplexing
  • Each major browser supports the ESM one by one
  • Native solves the problem of code dependency and reuse
  • More and more NPM packages are embracing ESM (although many package dependencies are not)
Bundle (Webpack) Bundleless(Vite/Snowpack)
The startup time Long, complete the package project Short, just start Server loading on demand
Build time Increases linearly with the volume of the project Build time complexity O(1)
Load performance The Bundle is loaded after the package is packaged The request is mapped to a local file
The cache capacity The cache utilization is generally affected by the split mode Cache utilization is near perfect
File to update repack Re-request a single file
Debugging experience SourceMap is usually needed for debugging Not strongly dependent on SourceMap, single file debugging
ecological Very perfect It’s not mature at the moment, but it’s growing fast
  • Bundle vs Bundleless

  • Bundle Refresh

  • Bundleless Refresh

Vite principle

Vite is divided into development mode and production mode

Development mode: , Vite provides a development server, and then combining with native ESM, when in the import code sends a resource request, Vite development server to intercept the request, according to the different file types, on the server to complete module rewrite (such as a single file parsing compilation, etc.) and the request processing, realize the real on-demand compilation, And then it goes back to the browser. The requested resource is compiled back on the server side on demand, bypassing the concept of packaging completely and not generating a large bundle. The server is always available, so initial startup in a development environment is very fast. And hot updates don’t slow down as more modules are added, because there is no bundle process after code changes.

Vite Server relies on the middleware for most of its logic. The middleware, after intercepting the request, completes the following:

  • Handle ESM syntax, such as converting import third-party dependency paths in business code to browser-recognized dependency paths;

  • Compile files such as.ts and.vue in real time.

  • Compile Sass/Less modules that need to be precompiled.

  • Establish a socket connection with the browser to implement HMR.

Production mode: Use Rollup to build source code.

Vite divides the code that needs to be handled into two broad categories

Third party dependencies: Most of this code is pure JavaScript and doesn’t change very often. Vite handles this code in a pre-bundle way. Why it should be pre-bundled is more on that later. Vite2 uses Esbulid to build this part of the code. Esbuild is go based and can be processed 10 to 100 times faster than a wrapper written in JavaScript, which is one reason why Vite is so fast during development.

Business code: Usually this part of the code, which is not pure JavaScript (e.g., JSX, Vue, etc.), is often modified and does not need to be loaded all at once (it can be loaded separately depending on the route).

Because Vite uses the native ESM, Vite itself simply compiles the code as needed and starts the static server. Modules are compiled and dynamically loaded into the current page only when requested by the browser.

Characteristics of the

  • NPM Dependency Resolving

The native ESM does not support bare Module imports. In other words, the native ESM only supports referencing resources by a relative or absolute path, not by a package name

import React from 'react'
Copy the code

Uncaught TypeError: Failed to resolve module specifier "test2.js". Relative references must start with either "/", "./", or ".. / ".

When we build projects using Webpack, we use this approach to import a third-party dependent package that we have installed. In fact, Webpack does this layer of transformation for us. Similarly, if we want to import a package like this in the ESM, we need to do this layer of path transformation.

  • Dependency pre-bundling

During development, Vite handles all code as native ESM, so Vite must convert CommonJS or UMD dependencies to native ESM reduction modules (reducing the number of requests). Vite converts ESM dependencies that contain many internal modules into a single module to improve subsequent page load performance. Pre-packaging needs to be executed only when dependencies change, but in projects with a large number of dependencies, each execution can take a long time. Vite used to use Rollup to do this, but in 2.0 we switched to ESbuild, which made the process dozens of times faster. Vite also helped us set up HTTP caches for these third-party dependent packages, so that we could read the caches directly when loading the same resource

  • Hot Module Replacement
  • TypeScript
  • Vue
  • JSX
  • CSS
  • The import. CSS file will inject its content into the page through tags with HMR support
  • Enhanced path resolution: @import and URL () paths in CSS are resolved by Vite’s path resolver to support alias and NPM dependencies.

Automatic URL rewriting: All URL () paths are automatically rewritten to ensure that they point to the correct file path during development and build.

  • CSS code splitting: When a module is loaded asynchronously, Vite automatically extracts the CSS from the module into a separate file, which is loaded via the style tag when the module is loaded.
  • CSS moudle support
  • CSS Pre-processors
  • Static Assets
  • JSON
  • Web Assembly
  • Web Workers
  • Dynamic Import Polyfill
  • Async Chunk Loading Optimization

When without optimization, when we went to an asynchronous loading module, only request and parse the current module, can find the module also import other modules, and then to send web request, this requires additional network traffic, but Vite can parsing code, know the current asynchronous module will depend on which directly depend on the module, Network requests can be sent in parallel.

Before optimization

Entry ---> A ---> C
Copy the code

The optimized

Entry ---> (A + C)
Copy the code

Caching

The file system cache Vite stores pre-bundle dependencies under node_modules/.vite. The pre-bundle is redone to update the cache only if the following occurs.

  • The dependencies list in your package.json
  • Package manager lockfiles, e.g. package-lock.json, yarn.lock, or pnpm-lock.yaml.
  • Relevant fields in your vite.config.js, if present.

Browser cache Vite Dev Server will set these third-party dependencies to HTTP strong caching to improve performance, only updating the Query ID to invalidate the previous cache if the dependencies change.

Automatic Dependency Discovery

If a dependency is not found in the cache, Vite will automatically look for it in node_modules and extract it into the cache. Vite will store the pre-bundle dependencies under node_modules/.vite

Why do production environments still need bundles

Although native ESM support is now widespread, it is still inefficient to use an unbundled ESM in production, even with HTTP2, due to the large number of network requests sent due to nested imports. In order to get the best load performance in production, it is best to bundle the code once (combining Tree Shaking, lazy loading and common chunk splitting techniques).

Why not use ESbuild in production

Esbuild is very fast and is already a very powerful Bundler, but some important features needed for application bindings are still under development — especially code splitting and CSS handling. Currently, Rollup is more mature and flexible in these areas. That said, when ESBuild stabilizes these features in the future, we do not rule out the possibility of using ESBuild in production releases

Comparison with Snowpack

Snowpack is also a local development server based on native ESM, with some similarities, but also some differences.

Production Build

Snowpack defaults to unbundled post-build files. It converts each file into individual building blocks and then makes those modules available to non-optimizers to do the actual bundling. The advantage of doing this is that you can use different end-bundlers (eg: webpack,rollup,esbuild) to meet specific needs.

Because Vite integrates build steps, Vite supports more features that are not yet supported in Snowpack.

  • Support for multiple pages

  • Automatic CSS segmentation

  • Supports dynamic introduction of polyfills

  • Library Mode

  • Optimized asynchronous chunk loading

  • The official Legacy Mode Plugin generates dual packages that support both modern and older browsers, and automatically delivers the correct package depending on the browser.

Faster Dependency pre-bundling Vite uses ESbuild for pre-bundling during development, which is much Faster than Rollup

Monorepo Support CSS Pre-Processor Support First Class Vue Support

Browser support

  • In the development environment, you need a native esM-enabled browser
  • In a production environment, browsers that support the native ESM are also required by default, but you can build packages that support older browsers using @Vitejs /plugin-legacy

In a Webpack-built project, our entry file is usually a JS, and index.html serves only as a template, whereas in a Vite built project, index.html serves as the entry file.

Refer to the article

Inside the Vite Principle: How did You achieve your latest work?

Vite relies on precompilation to shorten cold start times by several times

Talk about ESM, Bundle, Bundleless, Vite, Snowpack

Front end build from Bundleless

The Demo address

Vite-Study