396 lines
9.3 KiB
Markdown
396 lines
9.3 KiB
Markdown
# 9.3 环境与构建配置
|
||
|
||
:::tip 概述
|
||
本节说明前端项目的环境变量配置和 Vite 构建配置,包括开发环境和生产环境的差异配置。前端通过 `.env` 文件管理环境变量,Vite 自动根据模式加载对应的 `.env` 文件。
|
||
:::
|
||
|
||
## 环境变量文件
|
||
|
||
```text
|
||
ui/
|
||
├── .env # 所有环境通用配置
|
||
├── .env.development # 开发环境配置
|
||
├── .env.production # 生产环境配置
|
||
└── .env.local # 本地覆盖(不提交 git)
|
||
```
|
||
|
||
**加载优先级:** `.env.local` > `.env.{mode}` > `.env`
|
||
|
||
## 开发环境配置
|
||
|
||
### `.env.development`
|
||
|
||
```bash
|
||
# 开发服务器端口
|
||
VITE_PORT = 8001
|
||
|
||
# 公共基础路径(通常为 /)
|
||
VITE_PUBLIC_PATH = /
|
||
|
||
# API 接口基础路径(留空,由代理处理)
|
||
VITE_GLOB_API_URL =
|
||
|
||
# API 前缀(所有接口路径的前缀)
|
||
VITE_GLOB_API_URL_PREFIX = /api
|
||
|
||
# 代理配置(JSON 数组格式:[["前缀","目标地址"]])
|
||
VITE_PROXY = [["/api","http://admin.thinkphp6.naivevue/api"]]
|
||
|
||
# 上传接口地址
|
||
VITE_GLOB_UPLOAD_URL = /api/upload
|
||
|
||
# 图片访问地址(用于预览上传的图片)
|
||
VITE_GLOB_IMG_URL = http://file.thinkphp6.naivevue
|
||
|
||
# 是否在生产环境删除 console(开发环境保留)
|
||
VITE_DROP_CONSOLE = false
|
||
|
||
# 是否启用 Mock 数据(false = 使用真实后端 API)
|
||
VITE_USE_MOCK = false
|
||
```
|
||
|
||
## 生产环境配置
|
||
|
||
### `.env.production`
|
||
|
||
```bash
|
||
# 公共基础路径(通常为 /,如部署到子目录则设为 /subdir/)
|
||
VITE_PUBLIC_PATH = /
|
||
|
||
# API 接口基础路径(留空,由 Nginx 代理处理)
|
||
VITE_GLOB_API_URL =
|
||
|
||
# API 前缀
|
||
VITE_GLOB_API_URL_PREFIX = /api
|
||
|
||
# 上传接口地址
|
||
VITE_GLOB_UPLOAD_URL = /api/upload
|
||
|
||
# 图片访问地址(生产环境使用正式域名)
|
||
VITE_GLOB_IMG_URL = https://cdn.example.com
|
||
|
||
# 是否在生产环境删除 console
|
||
VITE_DROP_CONSOLE = true
|
||
|
||
# 是否启用 gzip 压缩
|
||
VITE_BUILD_COMPRESS = gzip
|
||
|
||
# 压缩后是否删除原文件
|
||
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
|
||
```
|
||
|
||
## 环境变量详解
|
||
|
||
### VITE_PORT — 开发服务器端口
|
||
|
||
```bash
|
||
VITE_PORT = 8001
|
||
```
|
||
|
||
| 环境 | 值 | 说明 |
|
||
|------|-----|------|
|
||
| 开发 | `8001` | 前端开发服务器端口 |
|
||
| 生产 | 不生效 | 生产环境由 Nginx 提供服务 |
|
||
|
||
### VITE_PUBLIC_PATH — 公共基础路径
|
||
|
||
```bash
|
||
VITE_PUBLIC_PATH = /
|
||
```
|
||
|
||
| 场景 | 值 | 说明 |
|
||
|------|-----|------|
|
||
| 根目录部署 | `/` | 默认值 |
|
||
| 子目录部署 | `/admin/` | 如 `https://example.com/admin/` |
|
||
|
||
### VITE_GLOB_API_URL — API 基础路径
|
||
|
||
```bash
|
||
VITE_GLOB_API_URL =
|
||
```
|
||
|
||
| 场景 | 值 | 说明 |
|
||
|------|-----|------|
|
||
| 开发(代理) | 留空 | 由 Vite proxy 转发 |
|
||
| 生产(同域) | 留空 | 由 Nginx 代理 |
|
||
| 生产(跨域) | `https://api.example.com` | 直接请求后端域名 |
|
||
|
||
### VITE_PROXY — 开发代理配置
|
||
|
||
```bash
|
||
VITE_PROXY = [["/api","http://admin.thinkphp6.naivevue/api"]]
|
||
```
|
||
|
||
**格式:** JSON 数组,每项为 `[前缀, 目标地址]`
|
||
|
||
**作用:** 将前端 `/api/*` 请求代理到后端地址,解决开发环境跨域问题。
|
||
|
||
**多代理示例:**
|
||
|
||
```bash
|
||
VITE_PROXY = [["/api","http://localhost:8080/api"],["/upload","http://localhost:8080/upload"]]
|
||
```
|
||
|
||
### VITE_GLOB_API_URL_PREFIX — API 前缀
|
||
|
||
```bash
|
||
VITE_GLOB_API_URL_PREFIX = /api
|
||
```
|
||
|
||
所有 API 请求路径的前缀,与后端路由前缀一致。
|
||
|
||
### VITE_GLOB_UPLOAD_URL — 上传接口地址
|
||
|
||
```bash
|
||
VITE_GLOB_UPLOAD_URL = /api/upload
|
||
```
|
||
|
||
文件上传组件使用的接口地址。
|
||
|
||
### VITE_GLOB_IMG_URL — 图片访问地址
|
||
|
||
```bash
|
||
# 开发环境
|
||
VITE_GLOB_IMG_URL = http://file.thinkphp6.naivevue
|
||
|
||
# 生产环境
|
||
VITE_GLOB_IMG_URL = https://cdn.example.com
|
||
```
|
||
|
||
用于预览上传的图片,拼接图片的完整 URL。
|
||
|
||
### VITE_DROP_CONSOLE — 删除 console
|
||
|
||
```bash
|
||
# 开发环境:保留 console(方便调试)
|
||
VITE_DROP_CONSOLE = false
|
||
|
||
# 生产环境:删除 console(安全+减小体积)
|
||
VITE_DROP_CONSOLE = true
|
||
```
|
||
|
||
### VITE_BUILD_COMPRESS — Gzip 压缩
|
||
|
||
```bash
|
||
VITE_BUILD_COMPRESS = gzip
|
||
```
|
||
|
||
启用 gzip 压缩后,构建产物会生成 `.gz` 文件,Nginx 配置 `gzip_static on` 可直接使用。
|
||
|
||
## 在代码中访问环境变量
|
||
|
||
```typescript
|
||
// 读取环境变量(VITE_ 前缀的变量才会暴露给客户端)
|
||
const apiUrl = import.meta.env.VITE_GLOB_API_URL;
|
||
const apiPrefix = import.meta.env.VITE_GLOB_API_URL_PREFIX;
|
||
const uploadUrl = import.meta.env.VITE_GLOB_UPLOAD_URL;
|
||
const imgUrl = import.meta.env.VITE_GLOB_IMG_URL;
|
||
|
||
// 完整 API 地址
|
||
const fullApiUrl = apiUrl + apiPrefix; // 如 "/api" 或 "https://api.example.com/api"
|
||
```
|
||
|
||
:::warning VITE_ 前缀
|
||
只有以 `VITE_` 开头的环境变量才会暴露给客户端代码,其他变量(如 `PORT`)不会被访问到。
|
||
:::
|
||
|
||
## Vite 配置
|
||
|
||
### `vite.config.ts`
|
||
|
||
```typescript
|
||
// ui/vite.config.ts(节选)
|
||
import { loadEnv } from 'vite';
|
||
import { createProxy } from './build/vite/proxy';
|
||
import { wrapperEnv } from './build/utils';
|
||
|
||
export default ({ command, mode }) => {
|
||
const root = process.cwd();
|
||
const env = loadEnv(mode, root);
|
||
const viteEnv = wrapperEnv(env);
|
||
const { VITE_PUBLIC_PATH, VITE_PORT, VITE_PROXY } = viteEnv;
|
||
|
||
return {
|
||
base: VITE_PUBLIC_PATH,
|
||
|
||
// Less 全局变量注入
|
||
css: {
|
||
preprocessorOptions: {
|
||
less: {
|
||
javascriptEnabled: true,
|
||
additionalData: `@import "src/styles/var.less";`,
|
||
},
|
||
},
|
||
},
|
||
|
||
// 开发服务器(代理由 VITE_PROXY 环境变量驱动)
|
||
server: {
|
||
host: true,
|
||
port: VITE_PORT,
|
||
proxy: createProxy(VITE_PROXY),
|
||
},
|
||
|
||
// 构建配置
|
||
build: {
|
||
target: 'es2015',
|
||
outDir: 'dist',
|
||
chunkSizeWarningLimit: 2000,
|
||
},
|
||
};
|
||
};
|
||
```
|
||
|
||
**代理实现**(`build/vite/proxy.ts`):读取 `VITE_PROXY` 数组,为每个前缀生成代理规则(`changeOrigin: true` + 去前缀 rewrite):
|
||
|
||
### 代理配置详解
|
||
|
||
```typescript
|
||
// build/vite/proxy.ts — 由 VITE_PROXY = [["/api","http://admin.thinkphp6.naivevue/api"]] 生成
|
||
{
|
||
'/api': {
|
||
target: 'http://admin.thinkphp6.naivevue/api', // 目标地址
|
||
changeOrigin: true, // 修改请求头 Origin
|
||
ws: true, // 支持 WebSocket
|
||
rewrite: (path) => path.replace(new RegExp('^/api'), ''), // 去掉前缀
|
||
},
|
||
}
|
||
```
|
||
|
||
**代理效果:**
|
||
|
||
```text
|
||
前端请求: GET /api/user/page
|
||
│
|
||
▼ Vite proxy
|
||
│
|
||
▼ 转发到: http://admin.thinkphp6.naivevue/api/user/page
|
||
```
|
||
|
||
## 构建命令
|
||
|
||
```bash
|
||
# 开发服务器(热更新)
|
||
pnpm dev
|
||
|
||
# 构建生产版本
|
||
pnpm build
|
||
|
||
# 预览构建结果(本地启动静态服务器)
|
||
pnpm preview
|
||
|
||
# ESLint 检查
|
||
pnpm lint:eslint
|
||
|
||
# ESLint 自动修复
|
||
pnpm lint:eslint --fix
|
||
|
||
# TypeScript 类型检查
|
||
pnpm type:check
|
||
```
|
||
|
||
### 构建产物
|
||
|
||
```text
|
||
ui/dist/
|
||
├── index.html # 入口文件
|
||
├── assets/
|
||
│ ├── index-xxx.js # 主 JS(带 hash)
|
||
│ ├── index-xxx.css # 主 CSS(带 hash)
|
||
│ └── vue-xxx.js # Vue 相关(分包)
|
||
├── favicon.ico
|
||
└── static/ # 静态资源
|
||
```
|
||
|
||
## 部署配置
|
||
|
||
### Nginx 配置
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name admin.example.com;
|
||
|
||
# 前端静态文件
|
||
root /data/www/admin/dist;
|
||
index index.html;
|
||
|
||
# SPA 路由(所有非文件请求都返回 index.html)
|
||
location / {
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
|
||
# API 代理到后端
|
||
location /api/ {
|
||
proxy_pass http://127.0.0.1:8080/api/;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
}
|
||
|
||
# 静态资源缓存
|
||
location /assets/ {
|
||
expires 30d;
|
||
add_header Cache-Control "public, immutable";
|
||
}
|
||
|
||
# Gzip 压缩
|
||
gzip on;
|
||
gzip_static on; # 优先使用 .gz 文件
|
||
gzip_types text/css application/javascript application/json;
|
||
}
|
||
```
|
||
|
||
## 多环境配置
|
||
|
||
### 测试环境
|
||
|
||
```bash
|
||
# .env.staging
|
||
VITE_GLOB_API_URL =
|
||
VITE_GLOB_API_URL_PREFIX = /api
|
||
VITE_GLOB_IMG_URL = http://file.thinkphp6.naivevue
|
||
VITE_DROP_CONSOLE = true
|
||
```
|
||
|
||
构建命令:
|
||
|
||
```bash
|
||
pnpm build --mode staging
|
||
```
|
||
|
||
### 环境变量对照表
|
||
|
||
| 变量 | 开发 | 测试 | 生产 |
|
||
|------|------|------|------|
|
||
| `VITE_PORT` | 8001 | - | - |
|
||
| `VITE_GLOB_API_URL` | 留空 | 留空 | 留空 |
|
||
| `VITE_GLOB_API_URL_PREFIX` | /api | /api | /api |
|
||
| `VITE_GLOB_IMG_URL` | http://file.xxx | https://test-cdn.xxx | https://cdn.xxx |
|
||
| `VITE_DROP_CONSOLE` | false | true | true |
|
||
| `VITE_USE_MOCK` | false | false | false |
|
||
|
||
## 常见问题
|
||
|
||
### 问题 1:开发环境 API 请求 404
|
||
|
||
**原因:** 代理配置错误或后端未启动。
|
||
|
||
**解决:** 检查 `.env.development` 中 `VITE_PROXY` 的目标地址是否正确。
|
||
|
||
### 问题 2:生产环境 API 请求跨域
|
||
|
||
**原因:** `VITE_GLOB_API_URL` 配置了跨域地址但后端未配置 CORS。
|
||
|
||
**解决:** 推荐留空,由 Nginx 代理处理(同域无跨域问题)。
|
||
|
||
### 问题 3:图片不显示
|
||
|
||
**原因:** `VITE_GLOB_IMG_URL` 配置错误。
|
||
|
||
**解决:** 检查图片访问地址是否正确,确保图片 URL 可直接访问。
|
||
|
||
### 问题 4:构建后体积过大
|
||
|
||
**原因:** 未启用 gzip 压缩或未分包。
|
||
|
||
**解决:** 启用 `VITE_BUILD_COMPRESS = gzip`(构建产物生成 `.gz`,配合 Nginx `gzip_static on`);如仍需拆分 chunk,可在 `vite.config.ts` 的 `build.rollupOptions.output.manualChunks` 中配置分包。
|