Files
gym-manage/docs/design/前端工程化建设文档.md
T
2026-03-08 22:00:52 +08:00

19 KiB
Raw Blame History

健身房管理系统前端工程化建设文档

文档编号: GYM-FE-ENG-001
版本: v1.0
日期: 2026-03-04
作者: 张翔
状态: 正式发布


文档修订历史

版本 日期 作者 修订内容
v1.0 2026-03-04 张翔 创建前端工程化建设文档

参考文档

  • 《健身房管理系统前端技术架构详细设计》 GYM-FE-ARCH-001
  • 《健身房管理系统前端开发规范》 GYM-FE-DEV-001
  • Vite 官方文档
  • GitHub Actions 文档

一、工程化概述

1.1 工程化目标

  • 提高开发效率:自动化重复性工作,减少手动操作
  • 保证代码质量:通过自动化检查和测试,确保代码质量
  • 统一开发规范:通过工具强制执行代码规范
  • 简化部署流程:自动化构建和部署,减少人为错误
  • 提升团队协作:统一开发环境和工具链

1.2 工程化体系

flowchart TB
    subgraph DevTools["开发工具链"]
        DT1["Node.js"]
        DT2["npm/yarn"]
        DT3["Git"]
        DT4["VSCode"]
    end

    subgraph BuildTools["构建工具"]
        BT1["Vite"]
        BT2["TypeScript"]
        BT3["ESLint"]
        BT4["Prettier"]
    end

    subgraph QualityTools["代码质量工具"]
        QT1["Husky"]
        QT2["Commitlint"]
        QT3["Lint-staged"]
        QT4["Stylelint"]
    end

    subgraph TestTools["测试工具"]
        TT1["Vitest"]
        TT2["Playwright"]
        TT3["Coverage"]
        TT4["Testing Library"]
    end

    subgraph CICD["CI/CD工具"]
        CD1["GitHub Actions"]
        CD2["Docker"]
        CD3["Nginx"]
        CD4["CDN"]
    end

    DevTools --> BuildTools
    BuildTools --> QualityTools
    QualityTools --> TestTools
    TestTools --> CICD

    style DevTools fill:#e1f5ff
    style BuildTools fill:#fff4e1
    style QualityTools fill:#f0e1ff
    style TestTools fill:#e1ffe1
    style CICD fill:#ffe1e1

二、构建工具配置

2.1 Vite配置

2.1.1 基础配置

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd())
  
  return {
    plugins: [vue()],
    resolve: {
      alias: {
        '@': resolve(__dirname, 'src'),
        '@components': resolve(__dirname, 'src/components'),
        '@utils': resolve(__dirname, 'src/utils'),
        '@api': resolve(__dirname, 'src/api'),
        '@stores': resolve(__dirname, 'src/stores')
      }
    },
    server: {
      port: 5173,
      host: true,
      open: true,
      proxy: {
        '/api': {
          target: env.VITE_API_BASE_URL,
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, '')
        }
      }
    },
    build: {
      outDir: 'dist',
      assetsDir: 'assets',
      sourcemap: mode === 'development',
      minify: 'terser',
      terserOptions: {
        compress: {
          drop_console: mode === 'production',
          drop_debugger: mode === 'production',
          pure_funcs: mode === 'production' ? ['console.log', 'console.info'] : []
        }
      },
      rollupOptions: {
        output: {
          manualChunks: {
            'vue-vendor': ['vue', 'vue-router', 'pinia'],
            'element-plus': ['element-plus'],
            'utils': ['lodash-es', 'dayjs'],
            'crypto': ['crypto-js', 'jsencrypt']
          }
        }
      },
      chunkSizeWarningLimit: 1000
    },
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: `@import "@/assets/styles/variables.scss";`
        }
      }
    }
  }
})

2.1.2 插件配置

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import Compression from 'vite-plugin-compression'
import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      imports: ['vue', 'vue-router', 'pinia'],
      dts: 'src/auto-imports.d.ts',
      eslintrc: {
        enabled: true
      }
    }),
    Components({
      resolvers: [ElementPlusResolver()],
      dts: 'src/components.d.ts'
    }),
    Compression({
      verbose: true,
      disable: false,
      threshold: 10240,
      algorithm: 'gzip',
      ext: '.gz'
    }),
    visualizer({
      open: false,
      gzipSize: true,
      brotliSize: true
    })
  ]
})

2.2 TypeScript配置

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "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/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"],
      "@api/*": ["src/api/*"],
      "@stores/*": ["src/stores/*"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

2.3 环境变量配置

// .env.development
VITE_APP_TITLE=健身房管理系统(开发环境)
VITE_API_BASE_URL=http://localhost:8080/api
VITE_UPLOAD_URL=http://localhost:8080/upload
VITE_WS_URL=ws://localhost:8080/ws
VITE_SENTRY_DSN=
VITE_CRYPTO_SECRET_KEY=your-secret-key-here
VITE_RSA_PUBLIC_KEY=your-rsa-public-key-here

// .env.production
VITE_APP_TITLE=健身房管理系统
VITE_API_BASE_URL=https://api.example.com/api
VITE_UPLOAD_URL=https://api.example.com/upload
VITE_WS_URL=wss://api.example.com/ws
VITE_SENTRY_DSN=https://xxx@sentry.io/xxx
VITE_CRYPTO_SECRET_KEY=your-production-secret-key-here
VITE_RSA_PUBLIC_KEY=your-production-rsa-public-key-here

// .env.staging
VITE_APP_TITLE=健身房管理系统(测试环境)
VITE_API_BASE_URL=https://staging-api.example.com/api
VITE_UPLOAD_URL=https://staging-api.example.com/upload
VITE_WS_URL=wss://staging-api.example.com/ws
VITE_SENTRY_DSN=https://xxx@sentry.io/xxx
VITE_CRYPTO_SECRET_KEY=your-staging-secret-key-here
VITE_RSA_PUBLIC_KEY=your-staging-rsa-public-key-here

三、代码规范工具

3.1 ESLint配置

// .eslintrc.json
{
  "extends": [
    "plugin:vue/vue3-recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier",
    "plugin:prettier/recommended"
  ],
  "parser": "vue-eslint-parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "parser": "@typescript-eslint/parser",
    "sourceType": "module"
  },
  "plugins": ["vue", "@typescript-eslint", "prettier"],
  "rules": {
    "vue/multi-word-component-names": "off",
    "vue/no-v-html": "warn",
    "@typescript-eslint/no-explicit-any": "warn",
    "@typescript-eslint/no-unused-vars": [
      "error",
      {
        "argsIgnorePattern": "^_",
        "varsIgnorePattern": "^_"
      }
    ],
    "@typescript-eslint/explicit-function-return-type": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "no-console": [
      "warn",
      {
        "allow": ["warn", "error"]
      }
    ],
    "no-debugger": "error",
    "prettier/prettier": "error"
  }
}

3.2 Prettier配置

// .prettierrc
{
  "semi": false,
  "singleQuote": true,
  "printWidth": 100,
  "trailingComma": "es5",
  "arrowParens": "avoid",
  "endOfLine": "lf",
  "tabWidth": 2,
  "useTabs": false,
  "bracketSpacing": true,
  "jsxSingleQuote": false,
  "proseWrap": "preserve"
}

3.3 Stylelint配置

// .stylelintrc.json
{
  "extends": ["stylelint-config-standard", "stylelint-config-prettier"],
  "rules": {
    "selector-class-pattern": "^[a-z][a-zA-Z0-9-__]*$",
    "selector-pseudo-class-no-unknown": [
      true,
      {
        "ignorePseudoClasses": ["deep", "global"]
      }
    ],
    "selector-pseudo-element-no-unknown": [
      true,
      {
        "ignorePseudoElements": ["v-deep", "v-global", "v-slotted"]
      }
    ]
  }
}

四、自动化工具

4.1 Husky配置

// package.json
{
  "scripts": {
    "prepare": "husky install",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
    "format": "prettier --write src/",
    "lint:style": "stylelint \"src/**/*.{css,scss,vue}\" --fix"
  }
}
# 初始化Husky
npx husky install

# 添加pre-commit钩子
npx husky add .husky/pre-commit "npx lint-staged"

# 添加commit-msg钩子
npx husky add .husky/commit-msg "npx commitlint --edit $1"

4.2 Lint-staged配置

// .lintstagedrc.json
{
  "*.{js,jsx,ts,tsx,vue}": [
    "eslint --fix",
    "prettier --write"
  ],
  "*.{css,scss,vue}": [
    "stylelint --fix"
  ],
  "*.{json,md}": [
    "prettier --write"
  ]
}

4.3 Commitlint配置

// commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'chore', 'ci']
    ],
    'type-case': [2, 'always', 'lower-case'],
    'type-empty': [2, 'never'],
    'scope-case': [2, 'always', 'lower-case'],
    'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],
    'subject-empty': [2, 'never'],
    'subject-full-stop': [2, 'never', '.'],
    'header-max-length': [2, 'always', 100]
  }
}

五、CI/CD流程

5.1 GitHub Actions配置

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run ESLint
        run: npm run lint
      
      - name: Run Prettier check
        run: npm run format:check

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run unit tests
        run: npm run test:unit
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          files: ./coverage/coverage-final.json
          fail_ci_if_error: true

  build:
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build
        run: npm run build
      
      - name: Upload build artifacts
        uses: actions/upload-artifact@v3
        with:
          name: dist
          path: dist/

5.2 CD配置

# .github/workflows/cd.yml
name: CD

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build
        run: npm run build
      
      - name: Deploy to server
        uses: easingthemes/ssh-deploy@v3
        with:
          SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
          REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
          REMOTE_USER: ${{ secrets.REMOTE_USER }}
          TARGET: /var/www/gym-manage/frontend
          SOURCE: dist/

六、项目脚手架

6.1 项目初始化

# 创建新项目
npm create vite@latest gym-manage-frontend -- --template vue-ts

# 进入项目目录
cd gym-manage-frontend

# 安装依赖
npm install

# 安装开发依赖
npm install -D \
  @vitejs/plugin-vue \
  unplugin-auto-import \
  unplugin-vue-components \
  sass \
  eslint \
  @typescript-eslint/parser \
  @typescript-eslint/eslint-plugin \
  eslint-plugin-vue \
  prettier \
  eslint-config-prettier \
  eslint-plugin-prettier \
  husky \
  lint-staged \
  @commitlint/cli \
  @commitlint/config-conventional \
  vitest \
  @vue/test-utils \
  @playwright/test \
  rollup-plugin-visualizer \
  vite-plugin-compression

# 安装生产依赖
npm install \
  vue \
  vue-router \
  pinia \
  axios \
  dayjs \
  lodash-es \
  element-plus \
  dompurify \
  crypto-js \
  jsencrypt \
  web-vitals

6.2 目录结构初始化

# 创建目录结构
mkdir -p src/{api,assets/{images,icons,styles},components/{base,business,layout},composables,config,directives,hooks,layouts,router,stores,types,utils,views}
mkdir -p src/test/{unit,e2e}
mkdir -p public

# 创建配置文件
touch .env.development .env.production .env.staging
touch .eslintrc.json .prettierrc .stylelintrc.json
touch tsconfig.json tsconfig.node.json

6.3 基础文件创建

// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'
import './assets/styles/main.scss'

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.use(router)
app.use(ElementPlus)

app.mount('#app')
// src/App.vue
<template>
  <router-view />
</template>

<script setup lang="ts">
</script>

<style>
#app {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
</style>

七、开发工具链

7.1 VSCode配置

// .vscode/settings.json
{
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll.stylelint": true
  },
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue"
  ],
  "typescript.tsdk": "node_modules/typescript/lib",
  "volar.takeOverMode.enabled": true,
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}
// .vscode/extensions.json
{
  "recommendations": [
    "vue.volar",
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "stylelint.vscode-stylelint",
    "bradlc.vscode-tailwindcss",
    "eamodio.gitlens"
  ]
}

7.2 Git配置

# .gitignore
node_modules
dist
dist-ssr
*.local
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
.DS_Store
*.log
coverage
.nyc_output
.env.local
.env.*.local

7.3 NPM脚本

// package.json
{
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "build:staging": "vue-tsc && vite build --mode staging",
    "preview": "vite preview",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
    "lint:style": "stylelint \"src/**/*.{css,scss,vue}\" --fix",
    "format": "prettier --write src/",
    "format:check": "prettier --check src/",
    "test": "vitest",
    "test:unit": "vitest run",
    "test:coverage": "vitest run --coverage",
    "test:e2e": "playwright test",
    "test:e2e:ui": "playwright test --ui",
    "test:e2e:headed": "playwright test --headed",
    "type-check": "vue-tsc --noEmit",
    "prepare": "husky install"
  }
}

八、最佳实践

8.1 依赖管理

8.1.1 依赖版本管理

// package.json
{
  "dependencies": {
    "vue": "^3.4.0",
    "vue-router": "^4.2.0",
    "pinia": "^2.1.0"
  },
  "devDependencies": {
    "vite": "^5.0.0",
    "typescript": "^5.0.0",
    "eslint": "^8.56.0"
  }
}

8.1.2 依赖安全检查

# 检查依赖漏洞
npm audit

# 自动修复依赖漏洞
npm audit fix

# 强制修复依赖漏洞
npm audit fix --force

8.2 性能监控

8.2.1 构建分析

# 生成构建分析报告
npm run build

# 查看分析报告
open stats.html

8.2.2 Bundle大小优化

// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          'vue-vendor': ['vue', 'vue-router', 'pinia'],
          'element-plus': ['element-plus'],
          'utils': ['lodash-es', 'dayjs']
        }
      }
    },
    chunkSizeWarningLimit: 500
  }
})

8.3 文档管理

8.3.1 README文档

# 健身房管理系统前端

## 项目介绍

健身房管理系统前端项目,基于Vue3 + Vite + TypeScript构建。

## 技术栈

- Vue 3.4+
- TypeScript 5.0+
- Vite 5.0+
- Pinia 2.1+
- Element Plus 2.5+

## 快速开始

### 安装依赖

\`\`\`bash
npm install
\`\`\`

### 开发

\`\`\`bash
npm run dev
\`\`\`

### 构建

\`\`\`bash
npm run build
\`\`\`

### 测试

\`\`\`bash
npm run test
\`\`\`

## 项目结构

\`\`\`
src/
├── api/           # API接口
├── assets/        # 静态资源
├── components/    # 组件
├── composables/   # Composables
├── config/        # 配置
├── router/        # 路由
├── stores/        # 状态管理
├── types/         # 类型定义
├── utils/         # 工具函数
└── views/         # 页面
\`\`\`

## 开发规范

详见 [前端开发规范](./docs/design/前端开发规范.md)

## 许可证

MIT

8.3.2 CHANGELOG文档

# Changelog

## [1.0.0] - 2026-03-04

### Added
- 会员管理功能
- 课程预约功能
- 扫码签到功能
- 数据统计功能

### Changed
- 升级Vue到3.4版本
- 优化构建配置

### Fixed
- 修复预约时间冲突问题
- 修复签到记录显示问题

### Security
- 添加XSS防护
- 添加CSRF防护

九、总结

本文档详细描述了健身房管理系统前端的工程化建设,包括:

  1. 工程化概述:工程化目标、工程化体系
  2. 构建工具配置Vite配置、TypeScript配置、环境变量配置
  3. 代码规范工具ESLint配置、Prettier配置、Stylelint配置
  4. 自动化工具Husky配置、Lint-staged配置、Commitlint配置
  5. CI/CD流程GitHub Actions配置、CD配置
  6. 项目脚手架:项目初始化、目录结构初始化、基础文件创建
  7. 开发工具链VSCode配置、Git配置、NPM脚本
  8. 最佳实践:依赖管理、性能监控、文档管理

通过遵循本文档的工程化建设指南,可以建立完善的前端工程化体系,提高开发效率、保证代码质量、简化部署流程。