仓库源文站点原文


title: "Learn the new frontend build tool Vite" description: "" added: "Jan 29 2022" tags: [web]

updatedDate: "Nov 28 2023"

Next Generation Frontend Tooling

When I need multiple different pages and create a React app that needs a backend, my go-to framework is Next.js. But sometimes I just want to create a React app, maybe for a demo or to start a project. I used to use create-react-app but these days I use Vite.

Use create-vite to start a Vite project by running npm create vite@latest. You can also try Vite online on StackBlitz at https://vite.new.

Vite consists of two major parts:

Once you've built the app, you may test it locally by running npm run preview command. It will boot up a local static web server that serves the files from dist. It's an easy way to check if the production build looks OK in your local environment.

Webpack and Vite

When you start the app in development, Webpack will bundle all of your code, and start the webpack-dev-server, the Express.js web server which will serve the bundled code. Within the bundled js file contains all modules for the app and need to regenerate the entire file when we change a file for HMR. It can often take an long wait to spin up a dev server, and even with HMR, file edits can take a couple seconds to be reflected in the browser.

Vite doesn't set out to be a new bundler. Rather, it's a pre-configured build environment using the Rollup bundler and a tool for local development. Vite pre-bundles dependencies in development mode using esbuild.

esbuild, which is written in Go, 10-100x faster than JavaScript-based bundlers, does the transpile things transforming into plain javascript. It will process and prebundle the dependencies into something works in the browser as native es-module. vite --force will ignore the dependency cache and reforce to process all the dependencies.

esbuild is highly optimized and compiled to native code. Using a JS runtime introduces a bottleneck that makes reaching those speeds impossible. However, esbuild-loader can still speed up your build by removing the bottlenecks created by babel-loader, ts-loader, Terser, etc.

Vite only support ES Modules, and parsing the native ES Modules means it will read the export and import lines from your code. It will convert those lines into HTTP requests back to the server, where it will again read the export and import lines and make new requests. 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 header.

<img alt="webpack" src="https://raw.gitmirror.com/kexiZeroing/blog-images/main/008vOhrAly1hc08w7udwkj31a20jmabm.jpg" width="600">

<img alt="vite" src="https://raw.gitmirror.com/kexiZeroing/blog-images/main/008vOhrAly1hc08w9irx0j313w0hwmyf.jpg" width="600">

Webpack

Vite

Popular Webpack plugins and their Vite equivalents

Issues with Vite

https://github.com/vitejs/vite/discussions/13697#discussioncomment-10241433

The page load speed for large web apps is the bottleneck in Vite's development experience. This bottleneck isn't related to HMR or slow Vite compilation speeds—both of these are already fast enough. The underlying cause is Vite's mechanism of sending ES modules directly to the browser.

Vite's current unbundle mechanism is not suitable for large web app development, as it reloads a large number of code files and generates numerous requests on every page refresh. While Vite has Dependency Pre-Bundling to solve third-party dependency issues, for large web app, our own codebase is also substantial. When a page has 500 source files simultaneously, the development experience becomes terrible.

Features

NPM Dependency Resolving

TypeScript

While Vite and other tools handle the actual transpilation of TypeScript to JavaScript, they don't provide type checking out of the box. This means that you could introduce errors into your code and Vite would continue running the dev server without telling you. Fortunately, we can configure TypeScript's CLI to allow for type checking without interfering with our other tools. By setting noEmit to true, this makes TypeScript act more like a linter than a transpiler.

CSS

Static Assets

Configuring Vite

When running vite from the command line, Vite will automatically try to resolve a config file named vite.config.js inside project root.

If the config needs to conditionally determine options based on the command (dev/serve or build), it can export a function instead. In Vite's API the command value is serve during dev (in the cli vite, vite dev, and vite serve are aliases), and build when building for production. For a full list of CLI options, run npx vite --help in your project.

More about Vite config: https://vitejs.dev/config

Using Plugins

Vite can be extended using plugins, which are based on Rollup's well-designed plugin interface with a few extra Vite-specific options. To use a plugin, it needs to be added to the devDependencies of the project and included in the plugins array in the vite.config.js config file.

Vite aims to provide out-of-the-box support for common web development patterns. A lot of the cases where a plugin would be needed in a Rollup project (https://github.com/rollup/plugins) are already covered in Vite. You can also check out awesome-vite plugins from the community.

Env Variables

Vite exposes env variables on the special import.meta.env object. Some built-in variables are available in all cases like import.meta.env.MODE.

Vite uses dotenv (.env) to load additional environment variables, and the loaded env variables are also exposed to your client source code via import.meta.env. To prevent accidentally leaking env variables to the client, only variables prefixed with VITE_ are exposed to your Vite-processed code.

Dynamic Image URL

import.meta.url is a native ESM feature that exposes the current module's URL. Combining it with the native URL constructor, we can obtain the full, resolved URL of a static asset using relative path from a JavaScript module.

The import.meta meta-property exposes context-specific metadata to a JavaScript module. It contains information about the module, such as the module's URL. import.meta is available in JavaScript modules; using it outside of a module is a syntax error.

import.meta.glob to import multiple modules from the file system is a Vite-only feature and is not a web or ES standard.

import fs from "node:fs/promises";

const fileURL = new URL("./someFile.txt", import.meta.url);
fs.readFile(fileURL, "utf8").then(console.log);
// only in Vite
const rawInput = import.meta.glob([
  './basic/**/*.*',
  './basic/**/.npmrc',
], {
  as: 'raw',
  eager: true,
})

// 1. Add this into Vite setup
const mdxFiles = import.meta.glob("./content/**.mdx");
// 2. and it compiles to
{
  "./content/foo.mdx": () => import("./content/foo.mdx"),
  "./content/bar.mdx": () => import("./content/bar.mdx"),
}

From Vue CLI to Vite

  1. Remove Vue CLI related dependencies in package.json.
  2. Remove sass-loader as Vite provides built-in support for the most common pre-processors out of the box.
  3. Add Vite as a dependency, as well as the Vue plugin for Vite.
  4. With the Vite plugins installed, remove the vue-template-compiler as that's handled by the Vite Vue plugins.
  5. Vite is a next generation build tool, let's proceed optimistically by only supporting the most modern browsers. Practically speaking, this means that we can remove Babel.
  6. Add a Vite config file vite.config.js in the root of the project. Import the Vue plugin and set @import alias there.
  7. Contrary to the Vue CLI, Vite actually puts the index.html file in the root of the project instead of the public directory, so you'll need to move it. And the JavaScript application is no longer auto injected so we need to include it like <script type="module" src="/src/main.js"></script>.
  8. Change the old vue-cli-service commands to Vite specific commands in package.json.
  9. You can no longer access environment variables on a process.env variable. Instead they can be found on import.meta.env.
  10. Remove all the magic comments for naming your dynamic imports as these are webpack specific comments (e.g. import(/* webpackChunkName: "about" */ "../views/About.vue")) and don't mean anything to Vite. Vite will automatically name your chunk based off of the original .vue file name combined with a hash.