从 webpack 切换到 Vite 是这两年前端圈比较明显的趋势。冷启动快、热更新快,用过就不想回去了。

但 Vite 的文档虽然不少,分散得比较零散,刚上手的时候不知道该怎么配。整理了一下我项目里常用的配置,基本覆盖了大部分场景。

项目创建

1
2
3
4
5
# React + TypeScript
npm create vite@latest my-app -- --template react-ts

# Vue + TypeScript
npm create vite@latest my-app -- --template vue-ts

创建完目录结构:

1
2
3
4
5
6
7
8
9
my-app/
├── public/ # 静态资源,不会被处理
├── src/
│ ├── assets/ # 会被 Vite 处理的静态资源
│ ├── components/
│ └── main.ts
├── index.html # 入口文件(注意是在根目录,不是 public)
├── vite.config.ts
└── tsconfig.json

基础配置

vite.config.ts 基本结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
plugins: [react()],

// 路径别名,@ 指向 src 目录
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},

// 开发服务器配置
server: {
port: 3000,
open: true, // 启动时自动打开浏览器
},
})

如果用 TypeScript,还要在 tsconfig.json 里配置路径别名(两处都要配,缺一不可):

1
2
3
4
5
6
7
8
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}

环境变量

Vite 有几种环境文件,按优先级:

1
2
3
4
.env                  # 所有环境都加载
.env.local # 所有环境,但被 .gitignore 忽略
.env.development # 只在开发环境(vite 命令)加载
.env.production # 只在生产环境(vite build 命令)加载

变量名必须以 VITE_ 开头才能在客户端代码里访问:

1
2
3
4
5
6
7
# .env.development
VITE_API_BASE_URL=http://localhost:8080
VITE_APP_TITLE=我的应用(开发)

# .env.production
VITE_API_BASE_URL=https://api.your-domain.com
VITE_APP_TITLE=我的应用

在代码里使用:

1
2
3
const baseUrl = import.meta.env.VITE_API_BASE_URL
const isDev = import.meta.env.DEV // Vite 内置,不需要 VITE_ 前缀
const isProd = import.meta.env.PROD

TypeScript 类型提示:在 src/vite-env.d.ts 里加:

1
2
3
4
5
6
7
8
9
10
/// <reference types="vite/client" />

interface ImportMetaEnv {
readonly VITE_API_BASE_URL: string
readonly VITE_APP_TITLE: string
}

interface ImportMeta {
readonly env: ImportMetaEnv
}

开发代理

开发时访问后端接口跨域,用代理转发:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
export default defineConfig({
server: {
proxy: {
// 把 /api 开头的请求转发到后端
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
// rewrite 可以改掉路径前缀
// 比如 /api/users → /users(把 /api 去掉)
rewrite: (path) => path.replace(/^\/api/, ''),
},

// 多个代理规则
'/upload': {
target: 'http://file-server.com',
changeOrigin: true,
},
},
},
})

打包优化

默认打包对小项目够用,项目大了需要手动优化。

代码分割:把第三方库和业务代码拆开,利用浏览器缓存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
export default defineConfig({
build: {
rollupOptions: {
output: {
// 把 node_modules 里的包单独打成一个 chunk
manualChunks(id) {
if (id.includes('node_modules')) {
// 可以按包名拆分,比如把 react 系单独一个包
if (id.includes('react') || id.includes('react-dom')) {
return 'react-vendor'
}
return 'vendor'
}
},
},
},
// 触发提示的 chunk 大小上限(默认 500kb)
chunkSizeWarningLimit: 1000,
},
})

开启 gzip 压缩:需要安装插件

1
npm install vite-plugin-compression -D
1
2
3
4
5
6
7
8
9
10
11
import compression from 'vite-plugin-compression'

export default defineConfig({
plugins: [
react(),
compression({
algorithm: 'gzip',
ext: '.gz',
}),
],
})

记得 Nginx 也要配合开启 gzip:

1
gzip_static on;  # 直接用 .gz 文件,不用实时压缩

图片等静态资源处理

1
2
3
4
5
export default defineConfig({
build: {
assetsInlineLimit: 4096, // 4kb 以下的图片转成 base64 内联
},
})

小图片内联可以减少 HTTP 请求,但别设太大,会让 JS 包变大。

按需引入组件库

以 Ant Design 为例:

1
2
npm install antd
npm install unplugin-vue-components unplugin-auto-import -D # Vue 项目用

React 项目,Ant Design 5.x 已经支持 Tree Shaking,直接引用组件就行,不需要额外插件:

1
import { Button, Input } from 'antd'  // 只打包用到的组件

Vue 项目配合 unplugin-vue-components

1
2
3
4
5
6
7
8
9
10
import Components from 'unplugin-vue-components/vite'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
plugins: [
Components({
resolvers: [AntDesignVueResolver({ importStyle: false })],
}),
],
})

完整配置参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
import compression from 'vite-plugin-compression'

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

return {
plugins: [
react(),
compression({ algorithm: 'gzip' }),
],

resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},

server: {
port: 3000,
proxy: {
'/api': {
target: env.VITE_API_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},

build: {
outDir: 'dist',
sourcemap: false, // 生产环境不生成 sourcemap
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor'
}
},
},
},
},
}
})

Vite 的配置项比 webpack 少很多,读起来也清晰,上手成本挺低的。遇到具体问题建议直接查官方文档,写得还挺详细。