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

14 KiB
Raw Blame History

情绪博物馆前端环境配置梳理

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. 注意事项

  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. 查看构建日志定位问题