14 KiB
14 KiB
情绪博物馆前端环境配置梳理
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)
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: 生产环境
环境配置接口
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)
{
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)
{
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)
{
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)
{
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)
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)
{
"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)
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)
export default {
plugins: {
tailwindcss: {}, // Tailwind CSS
autoprefixer: {}, // 自动添加CSS前缀
},
}
4. 代码规范配置
4.1 ESLint配置 (.eslintrc.cjs)
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)
{
"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)
基础配置
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)
{
"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)
#!/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版本
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 环境变量获取方式
// 在组件中使用环境变量
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:
export VITE_APP_ENV=dev
export VITE_API_BASE_URL=http://localhost:19089/api
npm run dev
Windows:
set VITE_APP_ENV=dev
set VITE_API_BASE_URL=http://localhost:19089/api
npm run dev
或者创建.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. 注意事项
- 环境变量: 必须以
VITE_开头才能在客户端使用 - API代理: 开发环境使用代理,生产环境使用真实域名
- WebSocket: 开发环境使用ws协议,生产环境使用wss协议
- 构建路径: 确保部署路径与
vite.config.ts中的base配置一致 - 类型检查: 构建前建议运行
npm run type-check确保类型安全 - 代码规范: 提交前运行
npm run lint确保代码质量
11. 故障排除
常见问题
- 构建失败: 检查TypeScript类型错误
- 代理不生效: 检查vite.config.ts中的proxy配置
- 环境变量未生效: 确保变量名以
VITE_开头 - 部署404: 检查nginx配置和base路径设置
- WebSocket连接失败: 检查协议和端口配置
调试技巧
- 使用浏览器开发者工具查看网络请求
- 检查控制台错误信息
- 使用Vue DevTools调试组件状态
- 查看构建日志定位问题