POST · 前端 · 文章

Vite 从入门到进阶

2026/11/13 · by ZHANG XING YUN · 阅读 1 次 · 3215 字 · 预计阅读 9 分钟

本文整理 Vite 学习路径:从核心原理与最小项目起步,逐层深入配置体系、环境变量、插件开发、按需加载、生产构建优化与部署策略,最后给出与 Webpack 的对比选型、常见问题。

  • 适用场景:Web / SPA / 微前端 / Electron 渲染层的现代构建
  • 技术栈:Vite 7.x,框架无关(Vue / React / Svelte 等均可接入)
  • 目标:开发极速、配置简洁、生产可控、迁移平滑

一、先明确它在解决什么问题

Vite 的核心定位是下一代前端构建工具,它要解决的核心痛点是:传统打包器(Webpack)在大型项目中开发服务器启动慢、热更新慢。

问题 Vite 的答案
冷启动要等几十秒? 开发环境不打包,按需编译,启动近乎瞬时
改一行代码 HMR 要等几秒? 只编译变更模块,HMR 通常 < 100ms
配置太复杂? 开箱即用,内置 TS/JSX/CSS/静态资源支持
生产构建慢? 基于 Rolldown(或 Rollup),构建速度与产物体积表现优秀

需要理解的边界:

维度 Vite 的表现
开发体验 极快,项目规模增大时优势更明显
生产构建 成熟稳定,但与开发环境的“快”是两套机制
生态成熟度 快速增长,主流框架与工具均已支持
旧浏览器 默认面向现代浏览器,需 @vitejs/plugin-legacy 兼容

三个原则:

  1. 开发靠浏览器,生产靠打包器:理解这两套机制,才能正确配置与优化。
  2. 配置即约定:默认配置覆盖大多数场景,不要过度定制。
  3. 生产优化靠 Rollup 配置:build.rollupOptions 是进阶优化的关键入口。

二、入门:环境与最小项目

2.1 环境要求

Vite 需要 Node.js 20.19+ 或 22.12+ 。验证:

node -v

2.2 创建项目

官方脚手架 create-vite 覆盖主流框架:

npm create vite@latest my-app -- --template vue-ts

可用模板:vanilla、vue、react、svelte、solid、lit、qwik 及其 -ts 变体 。

进入目录安装并启动:

cd my-app
npm install
npm run dev

浏览器访问 http://localhost:5173 即可。

2.3 最小项目结构

my-app/
├─ index.html          # 入口 HTML,Vite 的构建入口
├─ src/
│  └─ main.ts          # 应用入口
├─ vite.config.ts      # 配置文件(可选)
└─ package.json

与 Webpack 的关键区别:HTML 是入口,不是 JS。Vite 直接以 index.html 为起点,<script type="module" src="/src/main.ts"> 引用的模块会被自动处理 。

2.4 常用脚本

{
	"scripts": {
		"dev": "vite",
		"build": "vite build",
		"preview": "vite preview"
	}
}

preview 用于本地预览生产构建产物,不要用 dev 验证生产行为。


三、核心原理:为什么快

3.1 开发环境:按需编译

Webpack 的做法是:启动时先打包整个依赖图,再启动服务器。项目越大,启动越慢。

Vite 的做法是:直接启动服务器,浏览器请求哪个模块才编译哪个 。

浏览器请求 /src/main.ts
        ↓
Vite Dev Server 实时编译(esbuild/oxc)
        ↓
返回 ESM 模块给浏览器
        ↓
浏览器原生 ESM 执行

效果:冷启动时间与项目规模解耦。实测中型 Vue 项目(120+ 文件),Webpack 冷启动 8.2s,Vite 0.8s 。

3.2 热更新:只动变更的那一块

Webpack 的 HMR 需要重新计算依赖链并打包。Vite 的 HMR 只让变更模块及其 HMR 边界失效,重新编译单个文件即可 。

实测 JS 文件 HMR:Webpack 800ms~1.2s,Vite < 100ms 。

3.3 生产环境:打包是另一回事

开发环境的“不打包”只在 dev server 生效。执行 vite build 时,Vite 使用 Rolldown(新版本)或 Rollup 进行完整打包,并做 Tree Shaking、代码分割、压缩等优化 。


四、配置体系

4.1 配置文件

vite.config.ts 是默认配置入口,使用 defineConfig 获得类型提示:

import { defineConfig } from "vite";

export default defineConfig({
	server: {
		host: "127.0.0.1",
		port: 5173,
		strictPort: true
	},
	build: {
		outDir: "dist",
		sourcemap: true
	}
});

4.2 条件配置

根据 command(serve / build)或 mode 返回不同配置 :

export default defineConfig(({ command, mode }) => {
	if (command === "serve") {
		return { server: { port: 5173 } };
	}
	return { build: { sourcemap: false } };
});

4.3 常用配置项

配置 作用 建议
server.port 开发端口 固定端口便于调试
resolve.alias 路径别名 与 tsconfig paths 保持一致
server.proxy 开发代理 解决 CORS
build.target 构建目标 现代项目用默认或 esnext
build.rollupOptions Rollup 配置 分包、外部依赖

五、环境变量与模式

5.1 基本规则

只有以 VITE_ 为前缀的变量才会暴露给客户端代码,通过 import.meta.env 访问 :

# .env.development
VITE_API_URL=http://localhost:8080/api
const apiUrl = import.meta.env.VITE_API_URL;

5.2 内置变量

变量 含义
import.meta.env.MODE 当前模式(development / production)
import.meta.env.DEV 是否开发环境
import.meta.env.PROD 是否生产环境
import.meta.env.BASE_URL 部署基础路径

5.3 配置文件中读取环境变量

在 vite.config.ts 运行时,.env 文件尚未加载到 process.env。如果配置本身需要环境变量(如端口、代理目标),用 loadEnv :

import { defineConfig, loadEnv } from "vite";

export default defineConfig(({ mode }) => {
	const env = loadEnv(mode, process.cwd(), "");
	return {
		server: { port: Number(env.APP_PORT || 5173) }
	};
});

六、静态资源与 CSS

6.1 资源导入

import logoUrl from "./assets/logo.png";          // 返回 URL
import content from "./file.txt?raw";             // 返回文本内容
import Worker from "./worker?worker";             // Web Worker

批量导入用 import.meta.glob:

const modules = import.meta.glob("./assets/*.png", { eager: true });

6.2 CSS 处理

Vite 内置支持 CSS、CSS Modules、PostCSS 和预处理器(需安装对应依赖):

import "./style.css";                    // 全局样式
import styles from "./Component.module.css";  // CSS Modules

预处理器安装:

npm install -D sass less stylus

无需额外 loader 配置,Vite 自动识别。

6.3 资源内联阈值

build: {
	assetsInlineLimit: 4096  // 小于 4KB 的资源转为 base64
}

七、插件开发

7.1 插件结构

Vite 插件基于 Rollup 插件接口,并扩展了 Vite 特有钩子 :

import type { Plugin } from "vite";

export function myPlugin(): Plugin {
	return {
		name: "my-plugin",
		apply: "build",
		transform(code, id) {
			if (id.endsWith(".js")) {
				return { code: `/* built with vite */\n${code}`, map: null };
			}
		}
	};
}

7.2 钩子执行顺序

config → configResolved → configureServer(dev) → buildStart
→ resolveId → load → transform → buildEnd → closeBundle

7.3 Vite 特有钩子

钩子 用途
config 修改配置
configResolved 读取最终配置
configureServer 开发服务器中间件
transformIndexHtml 修改 HTML
handleHotUpdate 自定义 HMR 行为

7.4 常用社区插件

插件 作用
@vitejs/plugin-vue / @vitejs/plugin-react 框架支持
unplugin-auto-import 自动导入 API
unplugin-vue-components 组件自动注册
vite-plugin-compression 生成 gzip/brotli

八、按需加载与代码分割

8.1 动态导入

const module = await import("./heavy-module");

Vite 自动将其拆分为独立 chunk。

8.2 路由懒加载

const routes = [
	{ path: "/", component: () => import("@/pages/Home.vue") },
	{ path: "/about", component: () => import("@/pages/About.vue") }
];

8.3 手动分包

在 build.rollupOptions.output.manualChunks 中配置:

build: {
	rollupOptions: {
		output: {
			manualChunks: {
				vendor: ["vue", "vue-router", "pinia"],
				charts: ["echarts"]
			}
		}
	}
}

九、生产构建优化

9.1 构建目标

Vite 默认目标是 baseline-widely-available(约 2023 年中发布的浏览器版本)。如果确定用户环境现代,可设为 esnext 获得更小体积 :

build: { target: "esnext" }

需要兼容旧浏览器时,使用 @vitejs/plugin-legacy,它会为旧浏览器生成降级 chunk 。

9.2 压缩

Vite 默认用 esbuild(或 oxc)压缩,速度极快。如果追求极致体积,可切换 Terser(体积约小 2~5%,但速度慢):

build: {
	minify: "terser",
	terserOptions: { compress: { drop_console: true } }
}

9.3 移除调试代码

生产环境移除 console 和 debugger:

build: {
	terserOptions: {
		compress: { drop_console: true, drop_debugger: true }
	}
}

9.4 构建报告

npx vite build --report

生成 dist/stats.html,可视化 chunk 构成与体积大头 。

9.5 分包策略

策略 做法
路由级拆分 动态 import()
第三方库拆分 manualChunks 将 vue/react/echarts 等独立
运行时拆分 Vite 默认处理,无需额外配置

十、部署与缓存策略

10.1 基础路径

如果部署在子路径下:

export default defineConfig({ base: "/my-app/" });

10.2 缓存头

Vite 构建产物默认带 content hash,可设置长期缓存 :

文件 Cache-Control
assets/*.[hash].js/css public, max-age=31536000, immutable
index.html no-cache

10.3 压缩传输

在 Nginx 或 CDN 层开启 gzip/brotli,或使用 vite-plugin-compression 预生成压缩文件。

10.4 部署平台

平台 要点
Nginx try_files $uri $uri/ /index.html(SPA 路由)
Vercel / Netlify 自动识别 Vite,无需额外配置
对象存储 + CDN 注意缓存头与压缩配置

十一、调试与产物分析

问题 手段
产物过大 vite build --report + stats.html
构建慢 --debug 查看插件耗时,检查是否有重插件
依赖重复 npm ls <包名> / pnpm why <包名> 检查多版本共存
HMR 不生效 检查模块是否在 HMR 边界内,或是否有插件拦截
生产白屏 检查 base 配置、路由模式、资源路径

十二、与 Webpack 的对比

维度 Vite Webpack 5
开发启动 按需编译,极快,与规模解耦 全量打包,随规模变慢
HMR < 100ms 800ms~1.2s
配置复杂度 低,开箱即用 高,需理解 entry/output/loader/plugin
生态 快速增长,现代插件为主 极其成熟,历史积累深厚
生产构建 Rolldown/Rollup,质量高 成熟,优化手段丰富
旧浏览器 需 plugin-legacy 配置 target 即可
适用场景 新项目、追求开发体验 存量大型项目、需要极致控制

选型建议 :

  1. 新项目:优先 Vite,开发体验优势明显。
  2. 存量 Webpack 项目:如果构建稳定且无痛点,不急于迁移;如果需要提速,可评估 Rspack(兼容 Webpack 配置的 Rust 实现)。
  3. 需要大量 Webpack 专属插件:继续用 Webpack 或 Rspack。

十三、迁移要点

从 Webpack 迁移到 Vite 的核心步骤:

步骤 工作
1. 入口调整 确保有 index.html,<script type="module"> 指向入口
2. 环境变量 process.env.VUE_APP_* → import.meta.env.VITE_*
3. 静态资源 require() 改为 import 或 new URL()
4. 别名 resolve.alias 迁移到 Vite 的 resolve.alias
5. 代理 devServer.proxy → server.proxy
6. 插件替换 Webpack 专属插件找 Vite 替代品或移除
7. 构建验证 对比产物大小、首屏加载、路由懒加载是否正常

十四、常见问题

现象 原因 处理
生产构建后首屏很慢 未做路由懒加载,全部代码打进入口 用动态 import() 拆分路由
某依赖在构建后重复出现 多版本共存 npm ls 排查,统一版本或去重
静态资源 404 base 配置与部署路径不一致 设置正确的 base
环境变量读不到 缺少 VITE_ 前缀 改名为 VITE_XXX
HMR 不工作 插件拦截或模块不在边界内 检查插件 handleHotUpdate
旧浏览器白屏 默认 target 不兼容 使用 @vitejs/plugin-legacy
vite.config 读不到 .env 配置运行时 .env 未加载 用 loadEnv
构建产物过大 未压缩、未分包、target 过旧 检查 minify、manualChunks、target

十五、FAQ

Q1:Vite 和 Webpack 怎么选?

新项目、追求开发体验选 Vite;存量 Webpack 项目稳定运行则不必迁移,除非开发体验成为瓶颈。两者生产构建质量相当,Vite 开发优势压倒性 。

Q2:Vite 开发快,生产构建也快吗?

生产构建基于 Rolldown/Rollup,速度优于 Webpack,但不如开发服务器的“瞬时”体验。实测中型项目 Vite 构建约 6s,Webpack 约 18s 。

Q3:为什么开发环境不需要打包?

现代浏览器原生支持 ES Module。Vite 利用这一点,让浏览器直接请求模块,服务器按需编译返回,省去了打包步骤 。

Q4:生产环境可以不打包吗?

不推荐。生产环境需要 Tree Shaking、代码分割、压缩、hash 命名等优化,这些依赖打包器完成。Vite 的 build 就是做这件事。

Q5:import.meta.env 和 process.env 有什么区别?

process.env 在 Vite 客户端代码中不可用(除非手动 define)。import.meta.env 是 Vite 注入的,只有 VITE_ 前缀的变量会暴露 。

Q6:如何兼容旧浏览器?

使用 @vitejs/plugin-legacy,它生成两套 chunk:现代浏览器加载 ESM,旧浏览器加载降级版本 。

Q7:Vite 插件和 Rollup 插件什么关系?

Vite 插件兼容 Rollup 插件接口,同时扩展了 Vite 特有钩子(configureServer、transformIndexHtml 等)。

Q8:如何减小产物体积?

按优先级:路由懒加载 → 第三方库按需引入 → 设置 target: 'esnext'(如环境允许)→ 开启 drop_console → 检查是否有重复依赖 。

Q9:vite preview 能替代生产服务器吗?

不能。preview 仅用于本地验证构建产物,不具备生产级的缓存、压缩、并发能力。生产部署用 Nginx / CDN。

Q10:Vite 支持 SSR 吗?

支持。Vite 提供 SSR 相关 API,Nuxt、SvelteKit、Astro 等框架均基于 Vite 构建 SSR/SSG 应用。


附录:配置模板与检查清单

vite.config.ts 模板

import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
import { compression } from "vite-plugin-compression2";

export default defineConfig(({ mode }) => {
	const env = loadEnv(mode, process.cwd(), "");

	return {
		base: "/",
		plugins: [
			vue(),
			compression({ algorithm: "gzip" }),
			compression({ algorithm: "brotliCompress", ext: ".br" })
		],
		resolve: {
			alias: { "@": "/src" }
		},
		server: {
			port: 5173,
			proxy: {
				"/api": { target: env.VITE_API_TARGET || "http://localhost:8080", changeOrigin: true }
			}
		},
		build: {
			target: "esnext",
			sourcemap: false,
			chunkSizeWarningLimit: 800,
			rollupOptions: {
				output: {
					manualChunks: {
						vendor: ["vue", "vue-router", "pinia"]
					}
				}
			}
		}
	};
});
← 返回帖子 更多前端内容 →