Skip to content
Vite 配置与命令:CLI 与 vite.config
概述
Vite 的行为可以通过根目录下的 vite.config.js(也支持 .ts、.mjs、.cjs 等扩展名)和命令行参数控制。本章介绍最常用的配置项与 CLI 用法,包括开发服务器、代理、路径别名、构建输出、环境变量,以及配置文件与命令行参数的覆盖关系。
配置文件
vite 启动时自动解析项目根目录的 vite.config.js。当文件不在根目录或需要使用多个配置文件时,可通过 --config 显式指定:
bash
vite --config vite.config.dev.js配置文件可以导出一个对象,也可以导出一个函数。无论哪种形式,都推荐使用 Vite 提供的 defineConfig 工具函数包裹,以便编辑器提供完整的类型提示与补全(即便你使用的是纯 JavaScript)。
js
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
// 共享配置
server: { port: 3000 },
build: { outDir: 'dist' }
})defineConfig 本身是一个返回原对象的恒等函数,其作用是将 UserConfig 类型信息传递给编辑器。如果使用 TypeScript 编写配置文件,也可以写成 satisfies UserConfig,或配合 JSDoc 注解 /** @type {import('vite').UserConfig} */ 来获得同样的智能提示。
配置文件导出函数时,函数参数包含 command、mode、isSsrBuild、isPreview 等。开发服务器运行时 command 为 'serve',构建时则为 'build',利用这一点可以按不同阶段返回不同的配置。
js
export default defineConfig(({ command, mode }) => {
if (command === 'build') {
return { base: '/app/' }
}
return { server: { proxy: { '/api': 'http://localhost:4000' } } }
})如果函数内部需要执行异步操作(例如读取远端配置),可以导出一个 async 函数,defineConfig 依然能提供类型推导。
注意:在配置文件内部不能直接使用 import.meta.env 来访问 VITE_ 前缀的环境变量——那是给浏览器端代码使用的。后端配置需要读取 .env 文件时,应该使用 loadEnv,这一点将在“环境变量与模式”一节中展开。
开发服务器配置
开发服务器的行为主要由 server 字段控制,最常用的三个选项是 host、port 和 strictPort。
server.port:开发服务器端口,类型number,默认5173。server.host:服务器监听的 IP 地址,设为0.0.0.0或true表示监听所有地址(包括局域网)。命令行对应--host。server.strictPort:设为true后,若端口被占用则直接退出,不会自动尝试下一个可用端口。
默认情况下,如果 5173 端口已被占用,Vite 会依次尝试 5174、5175……最终实际监听的端口未必是配置文件中的值。这一点在联合调试时容易忽略。
js
export default defineConfig({
server: {
port: 3000,
host: '0.0.0.0',
strictPort: true
}
})执行 vite 会按上述配置监听 0.0.0.0:3000。如果端口 3000 被占,进程直接报错退出。命令行参数可以临时覆盖这些设置:
bash
vite --port 8080 --host此时实际端口为 8080,配置中的 port: 3000 不再生效。CLI 参数的优先级高于配置文件同名字段,这便是“命令行临时调整,配置文件记录默认值”的常见使用模式。
预览服务器(vite preview)也有独立的端口配置,默认 4173,选项位于 preview.port 等字段下,同样支持 strictPort 和 --port CLI 覆盖。如果只配置了 server 而未配置 preview,两者会各自使用不同的端口,不会互相干扰。
代理配置
在前后端分离开发中,前端开发服务器端口(如 5173)与后端 API 服务端口(如 4000)往往不一致,浏览器会因同源策略阻止跨域请求。此时可在开发服务器上配置代理,将对 /api 等路径的请求转发到后端。
server.proxy 的配置形式有两种:字符串简写和对象写法。
字符串简写直接把路径前缀映射到目标地址:
js
export default defineConfig({
server: {
proxy: {
'/api': 'http://localhost:4000'
}
}
})此时,前端发起 fetch('/api/users') 会被开发服务器转发到 http://localhost:4000/api/users,响应透传给浏览器。这种方式适合后端没有子路径前缀的简单场景。
对象写法可以更精细地控制代理行为:
js
proxy: {
'/api': {
target: 'http://localhost:4000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}target:转发目标地址。changeOrigin:修改请求头Origin为目标地址,避免后端因为Origin不匹配而拒绝请求。rewrite:重写路径。上例中,前端请求/api/users会被改写为/users再转发,让后端接收到的路由更加简洁。
server.proxy 的底层实现基于 http-proxy,还可以通过 configure 选项直接访问代理实例,完成日志或特殊事件处理。预览服务器也支持代理配置(preview.proxy),如果不单独设置,默认沿用 server.proxy 的配置。
注意:代理仅在开发服务器(以及预览服务器)中生效,生产构建不包含这个功能。部署到线上后,跨域问题需要由反向代理或者后端自身解决。
路径别名
模块路径中频繁出现的 ../../../ 会降低项目的可维护性。Vite 支持通过 resolve.alias 定义路径别名,将某个符号映射到实际的文件系统目录。
关键点在于,resolve.alias 配置的值必须是绝对路径,否则在不同文件引用时可能解析失败。通常配合 path.resolve 或 import.meta.url 来获取绝对路径。
js
import path from 'path'
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components')
}
}
})使用别名后,import 语句可以写成:
js
import utils from '@/utils/request'
import Header from '@components/Header'如果项目使用 TypeScript,还需要在 tsconfig.json 中添加 paths 映射,否则编辑器会报“找不到模块”:
json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"]
}
}
}Vite 不会自动同步 TypeScript 的路径设置,两者必须手动保持一致。
构建输出控制
生产构建的行为由 build 对象控制,三个最常用的选项是 outDir、assetsDir 和 emptyOutDir。
build.outDir:构建产物的输出目录,默认dist。build.assetsDir:静态资源(图片、字体、处理过的 CSS 等)的子目录,默认assets,生成结构如dist/assets/。build.emptyOutDir:构建前是否清空outDir。当outDir位于项目根目录之外时,默认值为false,否则默认为true。
假如想把产物输出到 output 目录,资源放到 static 子目录下:
js
export default defineConfig({
build: {
outDir: 'output',
assetsDir: 'static',
emptyOutDir: true
}
})执行 vite build 后,产物会写入 output 下,资源进入 output/static/,且每次构建前都会清空上一次的内容。如果担心误删,可以将 emptyOutDir 设为 false,或使用 CLI --emptyOutDir 参数覆盖。
这些选项也能通过 CLI 直接传入:
bash
vite build --outDir=build-output --assetsDir=res命令行传入的值同样会覆盖配置文件中的对应字段。
环境变量与模式
Vite 会从项目根目录加载以下文件,按优先级依次合并并加载环境变量:
.env—— 所有模式共享.env.local—— 本地覆盖,不应提交到版本控制系统.env.[mode]—— 特定模式下的变量,如.env.development.env.[mode].local—— 特定模式的本地变量,优先级最高
mode 默认由运行命令决定:vite 命令的 mode 为 development,vite build 的 mode 为 production。CLI 的 --mode 选项可以改变模式,例如 vite build --mode staging,此时会加载 .env.staging 等文件。
加载的变量中,只有以 VITE_ 开头的变量才会暴露给浏览器端代码,其他变量(如数据库密码)会被过滤掉。
在客户端代码中通过 import.meta.env 访问这些变量:
js
console.log(import.meta.env.VITE_API_URL)import.meta.env 内置以下几个字段:
MODE:当前模式字符串('development'、'production'等)BASE_URL:base配置对应的公共基础路径DEV:是否处于开发环境(布尔值)PROD:当前是否为 production 模式(布尔值)SSR:是否在服务端渲染环境中
例如,可以利用 DEV 在不同条件下输出日志:
js
if (import.meta.env.DEV) {
console.log('当前是开发环境')
}如果想在配置文件中读取 .env 的值,不能直接使用 import.meta.env,因为那是运行时注入给浏览器代码的。正确的做法是使用 loadEnv 辅助函数:
js
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
define: {
__API_URL__: JSON.stringify(env.VITE_API_URL)
}
}
})loadEnv 的第三个参数可以指定前缀,传入空字符串 '' 表示加载所有变量而不仅仅是 VITE_ 开头的,这在配置文件需要读取某些非客户端变量时很有用。
CLI 命令与配置覆盖
命令行接口提供了三个核心命令:
vite/vite dev/vite serve:启动开发服务器vite build:执行生产构建vite preview:预览构建产物(本地模拟构建结果运行)
每个命令都有对应的选项,很多选项与配置文件字段直接对应。例如:
bash
vite --port 3000 --host 0.0.0.0 --mode development
vite build --outDir output --assetsDir static --emptyOutDir
vite preview --port 5000 --strictPort当 CLI 参数与 vite.config.js 中的配置项控制同一行为时,CLI 传入的值优先级更高。Vite 先读取配置文件,再将命令行参数解析后合并,后者覆盖前者。因此,配置文件可以作为项目的“默认值仓库”,CI 或临时调试时通过命令行临时调整。
综合示例
以下将前面各节的内容整合到一份配置中。这份配置定义了开发时的代理和别名,同时设置了构建输出目录,并根据模式加载环境变量。
js
// vite.config.js
import { defineConfig, loadEnv } from 'vite'
import path from 'path'
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd(), '') // 加载所有变量
return {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
},
server: {
port: 3000,
host: '0.0.0.0',
strictPort: false,
proxy: {
'/api': {
target: 'http://localhost:4000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
build: {
outDir: 'dist',
assetsDir: 'assets',
emptyOutDir: true
},
define: {
// 向客户端代码注入自定义全局常量
__APP_NAME__: JSON.stringify(env.VITE_APP_TITLE || 'my-app')
}
}
})上面配置未按 command 做分支处理(开发与构建共用大部分配置),这在很多中小项目里已足够使用。如果需要根据开发或构建切换基础路径或插件集,则可通过 command 区分返回值。
启动时可以只用默认配置:
bash
vite也可以通过 CLI 临时调整端口:
bash
vite --port 8080构建并指定输出目录:
bash
vite build --outDir=output预览时指定端口并严格占用:
bash
vite preview --port 5000 --strictPort注意点
- CORS 风险:
server.cors默认只允许localhost、127.0.0.1和::1。如果设为true允许任意来源,任何网站都能向开发服务器发请求获取源码,不应在公网暴露时使用。 - 端口被占用时自动切换:开发服务器默认端口
5173,预览服务器默认端口4173,两者都会自动尝试下一个可用端口,除非显式设置strictPort为true。未设置strictPort时实际监听的端口可能与配置不同。 - 路径别名必须是绝对路径:
resolve.alias的值如果不写成绝对路径,在深层目录引用时可能解析失败。同时还需要同步 TypeScript 的paths设置。 emptyOutDir的默认行为:当outDir在根目录之外时,emptyOutDir默认为false。如果手动将outDir指向项目外的目录,且期望每次都清空,需要显式将该选项设为true。import.meta.env只在客户端代码中可用:配置文件中不能直接使用import.meta.env.VITE_xxx,必须通过loadEnv读取。- 代理只影响开发服务器:
server.proxy在vite build构建产物或部署到线上后不会起作用,线上跨域需另外处理。 - 模式只影响环境变量文件的加载:
mode不会改变import.meta.env.DEV等标志的值——DEV由命令本身决定:vite命令下DEV为true,vite build下DEV为false,与mode字符串无关。 - 配置函数中使用
mode区分逻辑:如果需要在配置中根据模式做不同设置(比如开发时加某个插件,构建时用另一个),直接在导出的函数中使用参数mode和command,而不是依赖import.meta.env。
