Files
happy-life-star/web-new/前端环境配置梳理.md
T

517 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 情绪博物馆前端环境配置梳理
## 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. 查看构建日志定位问题