517 lines
14 KiB
Markdown
517 lines
14 KiB
Markdown
# 情绪博物馆前端环境配置梳理
|
||
|
||
## 1. 项目概述
|
||
|
||
情绪博物馆前端基于Vue3 + TypeScript + Vite开发,采用现代化的前端技术栈,支持多环境部署。
|
||
|
||
### 技术栈
|
||
- **框架**: Vue 3.4.0
|
||
- **构建工具**: Vite 5.0.8
|
||
- **语言**: TypeScript 5.3.3
|
||
- **UI框架**: Element Plus 2.4.4
|
||
- **状态管理**: Pinia 2.1.7
|
||
- **路由**: Vue Router 4.2.5
|
||
- **样式**: Tailwind CSS 3.4.0
|
||
- **HTTP客户端**: Axios 1.6.2
|
||
- **WebSocket**: Socket.io-client 4.7.4, @stomp/stompjs 7.1.1
|
||
- **图表**: ECharts 5.4.3
|
||
- **工具库**: Day.js, Lodash-es, Zod
|
||
|
||
## 2. 环境配置文件
|
||
|
||
### 2.1 环境变量类型定义 (`src/types/env.d.ts`)
|
||
|
||
```typescript
|
||
interface ImportMetaEnv {
|
||
readonly VITE_APP_ENV: string // 应用环境
|
||
readonly VITE_APP_TITLE: string // 应用标题
|
||
readonly VITE_APP_VERSION: string // 应用版本
|
||
readonly VITE_API_BASE_URL: string // API基础URL
|
||
readonly VITE_WS_BASE_URL: string // WebSocket基础URL
|
||
readonly VITE_UPLOAD_URL: string // 文件上传URL
|
||
readonly VITE_DEBUG: string // 调试模式
|
||
readonly VITE_MOCK: string // Mock模式
|
||
readonly VITE_APP_DESCRIPTION: string // 应用描述
|
||
}
|
||
```
|
||
|
||
### 2.2 环境配置管理 (`src/config/env.ts`)
|
||
|
||
环境配置支持四种环境:
|
||
- **local**: 本地开发环境
|
||
- **dev**: 开发环境
|
||
- **test**: 测试环境
|
||
- **prod**: 生产环境
|
||
|
||
#### 环境配置接口
|
||
```typescript
|
||
interface EnvConfig {
|
||
name: string // 环境名称
|
||
apiBaseUrl: string // API基础URL
|
||
wsBaseUrl: string // WebSocket URL
|
||
uploadUrl: string // 文件上传URL
|
||
debug: boolean // 调试模式
|
||
mock: boolean // Mock模式
|
||
appTitle: string // 应用标题
|
||
appVersion: string // 应用版本
|
||
}
|
||
```
|
||
|
||
#### 各环境配置详情
|
||
|
||
**本地环境 (local)**
|
||
```typescript
|
||
{
|
||
name: '本地环境',
|
||
apiBaseUrl: 'http://localhost:19089/api',
|
||
wsBaseUrl: 'ws://localhost:19089/api',
|
||
uploadUrl: 'http://localhost:19089/api/upload',
|
||
debug: true,
|
||
mock: false,
|
||
appTitle: '情绪博物馆 - 本地',
|
||
appVersion: '1.0.0'
|
||
}
|
||
```
|
||
|
||
**开发环境 (dev)**
|
||
```typescript
|
||
{
|
||
name: '开发环境',
|
||
apiBaseUrl: 'http://localhost:19089/api',
|
||
wsBaseUrl: 'ws://localhost:19089/api',
|
||
uploadUrl: 'http://localhost:19089/api/upload',
|
||
debug: true,
|
||
mock: false,
|
||
appTitle: '情绪博物馆 - 开发',
|
||
appVersion: '1.0.0'
|
||
}
|
||
```
|
||
|
||
**测试环境 (test)**
|
||
```typescript
|
||
{
|
||
name: '测试环境',
|
||
apiBaseUrl: 'http://test.emotion-museum.com/api',
|
||
wsBaseUrl: 'ws://test.emotion-museum.com',
|
||
uploadUrl: 'http://test.emotion-museum.com/api/upload',
|
||
debug: false,
|
||
mock: false,
|
||
appTitle: '情绪博物馆 - 测试',
|
||
appVersion: '1.0.0'
|
||
}
|
||
```
|
||
|
||
**生产环境 (prod)**
|
||
```typescript
|
||
{
|
||
name: '生产环境',
|
||
apiBaseUrl: 'https://api.emotion-museum.com/api',
|
||
wsBaseUrl: 'wss://api.emotion-museum.com',
|
||
uploadUrl: 'https://api.emotion-museum.com/api/upload',
|
||
debug: false,
|
||
mock: false,
|
||
appTitle: '情绪博物馆',
|
||
appVersion: '1.0.0'
|
||
}
|
||
```
|
||
|
||
## 3. 构建配置
|
||
|
||
### 3.1 Vite配置 (`vite.config.ts`)
|
||
|
||
```typescript
|
||
export default defineConfig({
|
||
base: '/emotion-museum/', // 部署基础路径
|
||
plugins: [vue()],
|
||
resolve: {
|
||
alias: {
|
||
'@': resolve(__dirname, 'src'), // 路径别名
|
||
},
|
||
},
|
||
define: {
|
||
global: 'globalThis', // 全局变量定义
|
||
},
|
||
server: {
|
||
port: 5173, // 开发服务器端口
|
||
open: true, // 自动打开浏览器
|
||
proxy: { // 代理配置
|
||
'/api': {
|
||
target: 'http://localhost:19089',
|
||
changeOrigin: true,
|
||
secure: false,
|
||
}
|
||
}
|
||
},
|
||
build: {
|
||
outDir: 'dist', // 输出目录
|
||
sourcemap: false, // 不生成sourcemap
|
||
rollupOptions: {
|
||
external: (id) => { // 外部依赖处理
|
||
if (id.includes('echarts') && id.includes('extension')) {
|
||
return true
|
||
}
|
||
return false
|
||
},
|
||
output: {
|
||
manualChunks: { // 代码分割
|
||
vendor: ['vue', 'vue-router', 'pinia'],
|
||
elementPlus: ['element-plus'],
|
||
},
|
||
},
|
||
},
|
||
},
|
||
})
|
||
```
|
||
|
||
### 3.2 TypeScript配置 (`tsconfig.json`)
|
||
|
||
```json
|
||
{
|
||
"compilerOptions": {
|
||
"target": "ES2020", // 目标版本
|
||
"useDefineForClassFields": true,
|
||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||
"module": "ESNext",
|
||
"skipLibCheck": true,
|
||
"moduleResolution": "bundler", // 模块解析策略
|
||
"allowImportingTsExtensions": true,
|
||
"resolveJsonModule": true,
|
||
"isolatedModules": true,
|
||
"noEmit": true,
|
||
"jsx": "preserve",
|
||
"strict": true, // 严格模式
|
||
"noUnusedLocals": true,
|
||
"noUnusedParameters": true,
|
||
"noFallthroughCasesInSwitch": true,
|
||
"baseUrl": ".",
|
||
"paths": { // 路径映射
|
||
"@/*": ["src/*"]
|
||
},
|
||
"allowSyntheticDefaultImports": true,
|
||
"esModuleInterop": true,
|
||
"forceConsistentCasingInFileNames": true,
|
||
"types": ["node"]
|
||
},
|
||
"include": [
|
||
"src/**/*.ts",
|
||
"src/**/*.d.ts",
|
||
"src/**/*.tsx",
|
||
"src/**/*.vue",
|
||
"src/types/global.d.ts"
|
||
],
|
||
"references": [{ "path": "./tsconfig.node.json" }]
|
||
}
|
||
```
|
||
|
||
### 3.3 Tailwind CSS配置 (`tailwind.config.js`)
|
||
|
||
```javascript
|
||
export default {
|
||
content: [
|
||
"./index.html",
|
||
"./src/**/*.{vue,js,ts,jsx,tsx}",
|
||
],
|
||
theme: {
|
||
extend: {
|
||
colors: {
|
||
primary: { // 主色调
|
||
50: '#f0f9ff',
|
||
100: '#e0f2fe',
|
||
200: '#bae6fd',
|
||
300: '#7dd3fc',
|
||
400: '#38bdf8',
|
||
500: '#0ea5e9',
|
||
600: '#0284c7',
|
||
700: '#0369a1',
|
||
800: '#075985',
|
||
900: '#0c4a6e',
|
||
},
|
||
emotion: { // 情绪色彩
|
||
happy: '#fbbf24',
|
||
sad: '#3b82f6',
|
||
angry: '#ef4444',
|
||
calm: '#10b981',
|
||
excited: '#f97316',
|
||
anxious: '#8b5cf6',
|
||
},
|
||
// 设计系统颜色
|
||
'tech-blue': '#4A90E2',
|
||
'warm-orange': '#F5A623',
|
||
'light-gray': '#F7F8FA',
|
||
'text-dark': '#333333',
|
||
'text-medium': '#888888',
|
||
},
|
||
fontFamily: {
|
||
sans: ['Noto Sans SC', 'Inter', 'system-ui', 'sans-serif'],
|
||
},
|
||
animation: { // 自定义动画
|
||
'fade-in': 'fadeIn 0.5s ease-in-out',
|
||
'slide-up': 'slideUp 0.3s ease-out',
|
||
'bounce-gentle': 'bounceGentle 2s infinite',
|
||
},
|
||
keyframes: {
|
||
fadeIn: {
|
||
'0%': { opacity: '0' },
|
||
'100%': { opacity: '1' },
|
||
},
|
||
slideUp: {
|
||
'0%': { transform: 'translateY(20px)', opacity: '0' },
|
||
'100%': { transform: 'translateY(0)', opacity: '1' },
|
||
},
|
||
bounceGentle: {
|
||
'0%, 100%': { transform: 'translateY(0)' },
|
||
'50%': { transform: 'translateY(-5px)' },
|
||
},
|
||
},
|
||
},
|
||
},
|
||
plugins: [],
|
||
}
|
||
```
|
||
|
||
### 3.4 PostCSS配置 (`postcss.config.js`)
|
||
|
||
```javascript
|
||
export default {
|
||
plugins: {
|
||
tailwindcss: {}, // Tailwind CSS
|
||
autoprefixer: {}, // 自动添加CSS前缀
|
||
},
|
||
}
|
||
```
|
||
|
||
## 4. 代码规范配置
|
||
|
||
### 4.1 ESLint配置 (`.eslintrc.cjs`)
|
||
|
||
```javascript
|
||
module.exports = {
|
||
root: true,
|
||
extends: [
|
||
'plugin:vue/vue3-essential', // Vue3基础规则
|
||
'eslint:recommended', // ESLint推荐规则
|
||
'@vue/eslint-config-typescript', // TypeScript规则
|
||
'@vue/eslint-config-prettier/skip-formatting' // Prettier集成
|
||
],
|
||
parserOptions: {
|
||
ecmaVersion: 'latest'
|
||
},
|
||
rules: {
|
||
'vue/multi-word-component-names': 'off', // 允许单词组件名
|
||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], // 忽略下划线参数
|
||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境警告console
|
||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' // 生产环境警告debugger
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.2 Prettier配置 (`.prettierrc`)
|
||
|
||
```json
|
||
{
|
||
"semi": false, // 不使用分号
|
||
"singleQuote": true, // 使用单引号
|
||
"tabWidth": 2, // 缩进2个空格
|
||
"trailingComma": "es5", // ES5兼容的尾随逗号
|
||
"printWidth": 100, // 行宽100字符
|
||
"bracketSpacing": true, // 对象字面量括号内空格
|
||
"arrowParens": "avoid" // 箭头函数参数避免括号
|
||
}
|
||
```
|
||
|
||
## 5. HTTP请求配置
|
||
|
||
### 5.1 请求工具配置 (`src/utils/request.ts`)
|
||
|
||
#### 基础配置
|
||
```typescript
|
||
const instance = axios.create({
|
||
baseURL: envConfig.apiBaseUrl, // 从环境配置获取基础URL
|
||
timeout: 30000, // 30秒超时
|
||
headers: {
|
||
'Content-Type': 'application/json;charset=UTF-8'
|
||
}
|
||
})
|
||
```
|
||
|
||
#### 请求拦截器
|
||
- 自动添加Authorization头(Bearer Token)
|
||
- 生成请求ID用于追踪
|
||
- 调试模式下打印请求日志
|
||
|
||
#### 响应拦截器
|
||
- 统一处理业务状态码
|
||
- 特殊错误码处理(401、403、404、500等)
|
||
- 自动处理未授权情况
|
||
- 调试模式下打印响应日志
|
||
|
||
#### 错误处理
|
||
- 网络错误处理
|
||
- 服务器错误处理
|
||
- 业务错误处理
|
||
- 401未授权自动跳转登录
|
||
|
||
## 6. 部署配置
|
||
|
||
### 6.1 构建脚本 (`package.json`)
|
||
|
||
```json
|
||
{
|
||
"scripts": {
|
||
"dev": "vite", // 开发环境
|
||
"build": "vite build", // 生产构建
|
||
"build:check": "vue-tsc && vite build", // 类型检查+构建
|
||
"preview": "vite preview", // 预览构建结果
|
||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||
"type-check": "vue-tsc --noEmit", // TypeScript类型检查
|
||
"test": "vitest", // 单元测试
|
||
"test:e2e": "cypress run" // E2E测试
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.2 Linux部署脚本 (`deploy.sh`)
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# 部署脚本 - 将构建好的文件上传到服务器
|
||
|
||
SERVER_IP="47.111.10.27"
|
||
USERNAME="root"
|
||
REMOTE_PATH="/data/www/emotion-museum"
|
||
|
||
# 检查dist目录是否存在
|
||
if [ ! -d "dist" ]; then
|
||
echo "错误: dist目录不存在,请先运行 npm run build"
|
||
exit 1
|
||
fi
|
||
|
||
# 上传文件到服务器
|
||
scp dist/index.html "${USERNAME}@${SERVER_IP}:${REMOTE_PATH}/"
|
||
scp -r dist/assets "${USERNAME}@${SERVER_IP}:${REMOTE_PATH}/"
|
||
scp dist/test-*.html "${USERNAME}@${SERVER_IP}:${REMOTE_PATH}/"
|
||
```
|
||
|
||
### 6.3 Windows部署脚本 (`deploy.ps1`)
|
||
|
||
```powershell
|
||
# 部署脚本 - PowerShell版本
|
||
|
||
param(
|
||
[string]$ServerIP = "47.111.10.27",
|
||
[string]$Username = "root",
|
||
[string]$RemotePath = "/data/www/emotion-museum"
|
||
)
|
||
|
||
# 检查dist目录
|
||
if (-not (Test-Path "dist")) {
|
||
Write-Host "错误: dist目录不存在,请先运行 npm run build" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
# 上传文件到服务器
|
||
scp "dist/index.html" "${Username}@${ServerIP}:${RemotePath}/"
|
||
scp -r "dist/assets" "${Username}@${ServerIP}:${RemotePath}/"
|
||
scp "dist/test-*.html" "${Username}@${ServerIP}:${RemotePath}/"
|
||
```
|
||
|
||
## 7. 环境变量使用
|
||
|
||
### 7.1 环境变量获取方式
|
||
|
||
```typescript
|
||
// 在组件中使用环境变量
|
||
const apiUrl = import.meta.env.VITE_API_BASE_URL
|
||
const isDebug = import.meta.env.VITE_DEBUG === 'true'
|
||
const appTitle = import.meta.env.VITE_APP_TITLE
|
||
```
|
||
|
||
### 7.2 环境变量设置
|
||
|
||
开发时可以通过以下方式设置环境变量:
|
||
|
||
**Linux/Mac:**
|
||
```bash
|
||
export VITE_APP_ENV=dev
|
||
export VITE_API_BASE_URL=http://localhost:19089/api
|
||
npm run dev
|
||
```
|
||
|
||
**Windows:**
|
||
```cmd
|
||
set VITE_APP_ENV=dev
|
||
set VITE_API_BASE_URL=http://localhost:19089/api
|
||
npm run dev
|
||
```
|
||
|
||
**或者创建.env文件:**
|
||
```env
|
||
VITE_APP_ENV=dev
|
||
VITE_API_BASE_URL=http://localhost:19089/api
|
||
VITE_WS_BASE_URL=ws://localhost:19089/api
|
||
VITE_DEBUG=true
|
||
VITE_MOCK=false
|
||
```
|
||
|
||
## 8. 开发环境配置
|
||
|
||
### 8.1 开发服务器配置
|
||
- **端口**: 5173
|
||
- **自动打开**: 是
|
||
- **代理**: `/api` -> `http://localhost:19089`
|
||
- **热更新**: 启用
|
||
|
||
### 8.2 调试配置
|
||
- **Vue DevTools**: 支持
|
||
- **TypeScript**: 严格模式
|
||
- **ESLint**: 实时检查
|
||
- **Prettier**: 自动格式化
|
||
|
||
### 8.3 构建优化
|
||
- **代码分割**: 按模块分割
|
||
- **Tree Shaking**: 自动移除未使用代码
|
||
- **压缩**: 生产环境自动压缩
|
||
- **缓存**: 文件名包含哈希值
|
||
|
||
## 9. 生产环境配置
|
||
|
||
### 9.1 构建优化
|
||
- **Source Map**: 禁用
|
||
- **压缩**: 启用
|
||
- **代码分割**: 启用
|
||
- **CDN**: 支持
|
||
|
||
### 9.2 部署路径
|
||
- **基础路径**: `/emotion-museum/`
|
||
- **静态资源**: 自动添加哈希值
|
||
- **缓存策略**: 长期缓存静态资源
|
||
|
||
### 9.3 性能优化
|
||
- **懒加载**: 路由级别懒加载
|
||
- **预加载**: 关键资源预加载
|
||
- **压缩**: Gzip/Brotli压缩
|
||
- **缓存**: 浏览器缓存优化
|
||
|
||
## 10. 注意事项
|
||
|
||
1. **环境变量**: 必须以`VITE_`开头才能在客户端使用
|
||
2. **API代理**: 开发环境使用代理,生产环境使用真实域名
|
||
3. **WebSocket**: 开发环境使用ws协议,生产环境使用wss协议
|
||
4. **构建路径**: 确保部署路径与`vite.config.ts`中的`base`配置一致
|
||
5. **类型检查**: 构建前建议运行`npm run type-check`确保类型安全
|
||
6. **代码规范**: 提交前运行`npm run lint`确保代码质量
|
||
|
||
## 11. 故障排除
|
||
|
||
### 常见问题
|
||
1. **构建失败**: 检查TypeScript类型错误
|
||
2. **代理不生效**: 检查vite.config.ts中的proxy配置
|
||
3. **环境变量未生效**: 确保变量名以`VITE_`开头
|
||
4. **部署404**: 检查nginx配置和base路径设置
|
||
5. **WebSocket连接失败**: 检查协议和端口配置
|
||
|
||
### 调试技巧
|
||
1. 使用浏览器开发者工具查看网络请求
|
||
2. 检查控制台错误信息
|
||
3. 使用Vue DevTools调试组件状态
|
||
4. 查看构建日志定位问题 |