4、构建工具之Vite:Vite原理(ESM + esbuild),Vite项目初始化,Vite配置(别名/代理/环境变量),Vite插件机制,Vite与Webpack对比
好,咱们今天聊聊 Vite。说实话,Webpack 统治了前端构建好多年,但 Vite 的出现,确实让整个开发体验上了一个台阶。我记得我第一次用 Vite 启动项目时,那个秒开的开发服务器,真的让我愣了一下——嗯,这才对嘛。
4.1 Vite 的核心原理:ESM + esbuild
Vite 为什么这么快?说白了,它抓住了两个关键点:ES Modules 和 esbuild。
传统工具(比如 Webpack)在开发时,得先把所有模块打包成一个 bundle,再启动服务器。项目一大,这个过程就慢得让人抓狂。Vite 的思路完全不同——它利用浏览器原生支持的 ES Module 加载能力。
你在代码里写 import,浏览器直接发 HTTP 请求去拿对应的文件。Vite 只需要在请求到达时,对单个文件做轻量转换,然后返回给浏览器。这就叫「按需编译」。
核心区别一句话:Webpack 是「先打包,再启动」;Vite 是「先启动,再按需编译」。
那 esbuild 又是什么角色?它负责两件事:
- 预构建依赖:把 node_modules 里的 CommonJS 模块转成 ESM 格式,并合并成少量文件,减少请求数。
- 开发时的转换:比如 TypeScript、JSX 的编译,esbuild 用 Go 写的,速度比 Babel 快几十倍。
我在项目中遇到过一个问题:某个第三方库是 CommonJS 格式,Vite 预构建时自动处理了,但如果你用了动态 require(),它可能就报错。这时候你需要在 optimizeDeps.exclude 里排除它,或者手动配置 optimizeDeps.include。
小提示:Vite 的生产构建用的是 Rollup,不是 esbuild。因为 esbuild 的代码分割和 CSS 处理还不够成熟。开发和生产用两套工具,各取所长。
4.2 Vite 项目初始化
初始化一个 Vite 项目,简单到令人发指。你只需要一行命令:
npm create vite@latest my-vite-app -- --template vue-ts
或者用 yarn:
yarn create vite my-vite-app --template react-ts
它会问你选什么框架模板。我个人习惯用 vue-ts 或 react-ts,因为 TypeScript 现在几乎是标配了。
初始化完成后,目录结构大概是这样的:
my-vite-app/
├── index.html # 入口 HTML,Vite 把它当入口文件
├── package.json
├── tsconfig.json
├── vite.config.ts # 核心配置文件
├── src/
│ ├── main.ts
│ ├── App.vue
│ └── ...
└── public/
注意,index.html 直接放在根目录,而不是 public 里。Vite 把它当作模块图的入口,里面引用的 <script type="module" src="/src/main.ts"> 就是启动点。
避坑指南:我曾经把 index.html 放到 public 目录下,结果 Vite 死活不识别。记住,index.html 必须在项目根目录,public 只放静态资源(图片、字体等)。
4.3 Vite 配置:别名、代理、环境变量
Vite 的配置集中在 vite.config.ts 里。咱们一个一个说。
4.3.1 路径别名
你肯定不想写 ../../components/ 这种路径。配置别名很简单:
import { defineConfig } from 'vite'
import path from 'path'
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
}
}
})
然后你在代码里就能写 import Button from '@/components/Button.vue'。记得在 tsconfig.json 里也加上对应的 paths 配置,不然 TypeScript 会报红。
4.3.2 代理配置
开发时跨域问题,Vite 用 server.proxy 解决:
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
这样你请求 /api/users 就会被代理到 http://localhost:3000/users。我在项目中遇到过一个问题:如果后端用了 WebSocket,记得加上 ws: true。
4.3.3 环境变量
Vite 用 import.meta.env 来访问环境变量。默认有三个:
import.meta.env.MODE:当前模式(development/production)import.meta.env.BASE_URL:部署基础路径import.meta.env.PROD:是否为生产环境
自定义环境变量需要以 VITE_ 开头,放在 .env 文件中:
# .env
VITE_API_BASE_URL=https://api.example.com
# .env.development
VITE_API_BASE_URL=http://localhost:3000
然后在代码里用 import.meta.env.VITE_API_BASE_URL 读取。注意,只有 VITE_ 开头的变量才会暴露给客户端,其他变量只在服务端配置中可用。
小技巧:如果你需要类型提示,可以在 src/env.d.ts 里声明:interface ImportMetaEnv { readonly VITE_API_BASE_URL: string }
4.4 Vite 插件机制
Vite 的插件系统基于 Rollup 插件接口,但扩展了一些 Vite 特有的钩子。说白了,插件就是一个对象,包含一些生命周期函数。
一个最简单的插件长这样:
// my-plugin.ts
export default function myPlugin() {
return {
name: 'my-plugin',
transform(code, id) {
if (id.endsWith('.vue')) {
// 对 .vue 文件做点什么
return code.replace(/console\.log/g, '')
}
}
}
}
然后在 vite.config.ts 里使用:
import myPlugin from './my-plugin'
export default defineConfig({
plugins: [myPlugin()]
})
Vite 的插件钩子分为两类:
- 通用钩子:和 Rollup 共享,比如
resolveId、load、transform、generateBundle - Vite 特有钩子:比如
config(修改配置)、configureServer(配置开发服务器)、handleHotUpdate(处理 HMR)
我在项目中写过一个小插件,用来在开发时自动生成路由配置。用 configureServer 钩子监听文件变化,然后动态更新路由表。嗯,这个思路你可以参考一下。
常用插件推荐:
@vitejs/plugin-vue:Vue 单文件组件支持@vitejs/plugin-react:React JSX 支持vite-plugin-pages:基于文件系统的路由vite-plugin-svg-icons:SVG 图标管理
4.5 Vite 与 Webpack 对比
咱们来做个对比,这样你心里更有数。
| 维度 | Vite | Webpack |
|---|---|---|
| 开发服务器启动 | 秒级(按需编译) | 分钟级(全量打包) |
| 热更新速度 | 毫秒级(只更新修改的模块) | 秒级(需要重新打包) |
| 构建工具 | 开发用 esbuild,生产用 Rollup | 自研打包器 |
| 配置复杂度 | 低(开箱即用) | 高(需要大量配置) |
| 插件生态 | 较新,但增长快 | 成熟,插件丰富 |
| 浏览器兼容 | 生产构建支持 ES2015+ | 可配置到 ES5 |
| 适用场景 | 新项目、现代浏览器 | 老项目、需要兼容 IE |
你可能会问:那是不是所有新项目都应该用 Vite?我的答案是:大部分是,但不是全部。
如果你要兼容 IE11,或者项目里用了很多 Webpack 特有的 loader 和插件,那迁移成本可能比较高。但如果你是从零开始,或者项目已经用上了 ES Module,Vite 绝对是更好的选择。
避坑指南:我曾经把一个用了大量 Webpack 自定义 loader 的老项目迁移到 Vite,结果发现有些 loader 没有 Vite 替代品,最后不得不自己写插件。所以,迁移前一定要评估好插件生态的覆盖度。
好了,Vite 的核心内容就这些。从原理到配置,从插件到对比,你应该能感受到 Vite 的设计哲学——用现代浏览器的能力,换取开发者的效率。下一章咱们聊聊构建产物的优化,包括代码分割、Tree Shaking 和缓存策略,这些在生产环境中非常关键。