Project-Ideas:前端工程化项目实战:从0到1构建企业级前端架构

Project-Ideas:前端工程化项目实战:从0到1构建企业级前端架构

【免费下载链接】Project-Ideas-And-Resources A Collection of application ideas that can be used to improve your coding skills ❤. 【免费下载链接】Project-Ideas-And-Resources 项目地址: https://gitcode.com/GitHub_Trending/pr/Project-Ideas-And-Resources

你还在为前端项目混乱的代码结构头疼吗?还在手动配置Webpack到深夜吗?本文基于Project-Ideas-And-Resources项目实战经验,为你系统梳理前端工程化全流程,从环境搭建到性能优化,从模块化开发到CI/CD部署,一站式解决90%的工程化痛点。读完本文你将获得:

  • 3套企业级工程化架构模板(React/Vue/ vanilla JS)
  • 15个前端工程化关键配置清单
  • 7种性能优化实战方案
  • 完整的CI/CD自动化部署流程

一、前端工程化现状与痛点分析

1.1 开发效率对比表

开发模式环境配置时间构建速度代码质量保障团队协作效率
传统手动开发3-5小时/项目慢(无缓存)依赖人工检查低(文件冲突频发)
基础工程化30分钟(模板复用)中(基础缓存)部分自动化(lint)中(分支管理)
企业级工程化5分钟(一键生成)快(多级缓存)全流程自动化高(标准化协作)

1.2 常见工程化痛点

mermaid

二、工程化架构设计:核心技术栈选型

2.1 主流构建工具对比

工具构建速度配置复杂度生态完善度学习曲线最佳适用场景
Webpack★★★☆☆★★★★☆★★★★★★★★★☆大型复杂应用
Vite★★★★★★★☆☆☆★★★★☆★★☆☆☆Vue/React新项目
Rollup★★★★☆★★★☆☆★★★☆☆★★★☆☆类库开发
Parcel★★★★☆★☆☆☆☆★★☆☆☆★☆☆☆☆快速原型开发

选型建议:新项目优先选择Vite,构建速度比Webpack快10-100倍;存量项目可逐步迁移或使用Webpack 5提升性能。

2.2 完整技术栈组合

mermaid

三、从零搭建企业级工程化架构

3.1 项目初始化(Vite + React + TypeScript)

# 使用国内镜像初始化项目
npm create vite@latest my-project -- --template react-ts --registry=https://registry.npmmirror.com

cd my-project

# 安装依赖(国内CDN加速)
npm install --registry=https://registry.npmmirror.com

# 启动开发服务器
npm run dev

3.2 核心配置文件详解

vite.config.ts 配置
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
import legacy from '@vitejs/plugin-legacy';
import { visualizer } from 'rollup-plugin-visualizer';
import viteCompression from 'vite-plugin-compression';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    // 兼容旧浏览器
    legacy({
      targets: ['defaults', 'not IE 11']
    }),
    // 构建体积分析
    visualizer({
      open: true,
      gzipSize: true,
      brotliSize: true
    }),
    // 资源压缩
    viteCompression({
      algorithm: 'gzip',
      threshold: 10240 // 大于10kb的文件才压缩
    })
  ],
  resolve: {
    // 路径别名配置
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
      '@utils': path.resolve(__dirname, './src/utils')
    }
  },
  server: {
    port: 3000,
    open: true,
    proxy: {
      // 接口代理配置
      '/api': {
        target: 'https://api.example.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    },
    // 启用HTTPS(开发环境)
    https: false
  },
  build: {
    // 构建目标浏览器
    target: 'es2015',
    // 输出目录
    outDir: 'dist',
    // 静态资源目录
    assetsDir: 'assets',
    // 代码分割配置
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          utils: ['lodash', 'axios'],
          components: ['@mui/material']
        }
      }
    },
    // 生产环境sourcemap
    sourcemap: false,
    // 资源内联限制
    assetsInlineLimit: 4096 // 4kb以下内联
  },
  // CSS配置
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true
      }
    },
    // CSS模块化配置
    modules: {
      generateScopedName: '[name]__[local]___[hash:base64:5]'
    }
  },
  // 环境变量配置
  envPrefix: 'APP_',
  // 缓存配置
  cacheDir: 'node_modules/.vite_cache'
});
ESLint 和 Prettier 配置
// .eslintrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended', // 整合prettier
    'plugin:import/recommended',
    'plugin:import/typescript'
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    ecmaVersion: 'latest',
    sourceType: 'module'
  },
  plugins: [
    'react',
    'react-refresh',
    '@typescript-eslint',
    'prettier',
    'import',
    'unused-imports'
  ],
  settings: {
    react: {
      version: 'detect'
    },
    'import/resolver': {
      typescript: {
        project: './tsconfig.json'
      }
    }
  },
  rules: {
    'react/react-in-jsx-scope': 'off',
    'react/prop-types': 'off',
    'no-unused-vars': 'off',
    '@typescript-eslint/no-unused-vars': 'off',
    'unused-imports/no-unused-imports': 'error',
    'unused-imports/no-unused-vars': [
      'warn',
      {
        vars: 'all',
        varsIgnorePattern: '^_',
        args: 'after-used',
        argsIgnorePattern: '^_'
      }
    ],
    'import/order': [
      'error',
      {
        'newlines-between': 'always',
        groups: [
          ['builtin', 'external'],
          'internal',
          ['parent', 'sibling', 'index']
        ]
      }
    ],
    'react/self-closing-comp': 'error',
    'react/jsx-sort-props': [
      'error',
      {
        callbacksLast: true,
        shorthandFirst: true,
        noSortAlphabetically: false,
        reservedFirst: true
      }
    ]
  }
};
// .prettierrc.js
module.exports = {
  printWidth: 120, // 每行代码最大长度
  tabWidth: 2, // tab缩进宽度
  useTabs: false, // 使用空格代替tab
  semi: true, // 语句结尾加分号
  singleQuote: true, // 使用单引号
  quoteProps: 'as-needed', // 对象属性引号按需添加
  trailingComma: 'all', // 多行时末尾加逗号
  bracketSpacing: true, // 对象字面量括号间加空格
  arrowParens: 'always', // 箭头函数参数始终带括号
  rangeStart: 0,
  rangeEnd: Infinity,
  requirePragma: false,
  insertPragma: false,
  proseWrap: 'preserve', // markdown文本不自动换行
  htmlWhitespaceSensitivity: 'css',
  endOfLine: 'lf', // 行尾换行符格式
  embeddedLanguageFormatting: 'auto',
  singleAttributePerLine: true // 每个JSX属性单独一行
};

3.3 Git提交规范与自动化

# 安装提交相关依赖
npm install --save-dev husky lint-staged @commitlint/cli @commitlint/config-conventional commitizen cz-conventional-changelog --registry=https://registry.npmmirror.com

# 初始化husky
npx husky install

# 添加husky钩子
npx husky add .husky/pre-commit "npx lint-staged"
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"
npx husky add .husky/pre-push "npm run test:unit"
// package.json 添加配置
{
  "scripts": {
    "prepare": "husky install",
    "commit": "git-cz",
    "lint": "eslint . --ext ts,tsx,js,jsx --fix",
    "format": "prettier --write .",
    "test:unit": "vitest run",
    "test:coverage": "vitest run --coverage"
  },
  "lint-staged": {
    "*.{ts,tsx,js,jsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{css,less,scss}": [
      "prettier --write"
    ],
    "*.{json,md}": [
      "prettier --write"
    ]
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
}
// commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional']
};

四、模块化与组件设计最佳实践

4.1 项目目录结构

my-project/
├── public/                 # 静态资源
├── src/
│   ├── api/                # API请求
│   │   ├── client.ts       # 请求客户端配置
│   │   ├── modules/        # 按模块组织API
│   │   └── types.ts        # API类型定义
│   ├── assets/             # 资源文件
│   │   ├── images/         # 图片资源
│   │   ├── styles/         # 全局样式
│   │   └── icons/          # 图标资源
│   ├── components/         # 共享组件
│   │   ├── common/         # 通用基础组件
│   │   ├── business/       # 业务组件
│   │   └── layout/         # 布局组件
│   ├── hooks/              # 自定义Hooks
│   ├── pages/              # 页面组件
│   │   ├── Home/
│   │   │   ├── components/ # 页面私有组件
│   │   │   ├── hooks/      # 页面私有hooks
│   │   │   ├── types.ts    # 页面类型定义
│   │   │   ├── index.tsx   # 页面入口
│   │   │   └── style.less  # 页面样式
│   │   └── ...
│   ├── router/             # 路由配置
│   ├── store/              # 状态管理
│   ├── types/              # 全局类型定义
│   ├── utils/              # 工具函数
│   ├── App.tsx             # 应用入口
│   └── main.tsx            # 渲染入口
├── .env.development        # 开发环境变量
├── .env.production         # 生产环境变量
├── .env.test               # 测试环境变量
├── index.html              # HTML模板
├── package.json            # 项目配置
├── tsconfig.json           # TypeScript配置
├── vite.config.ts          # Vite配置
├── .eslintrc.js            # ESLint配置
├── .prettierrc.js          # Prettier配置
└── README.md               # 项目说明文档

4.2 组件设计模式示例:复合组件模式

// src/components/common/Dropdown/Dropdown.tsx
import React, { createContext, useContext, useState, ReactNode } from 'react';
import './Dropdown.less';

// 定义Context类型
type DropdownContextType = {
  isOpen: boolean;
  toggle: () => void;
  close: () => void;
  selectedValue: string | null;
  setSelectedValue: (value: string) => void;
};

// 创建Context
const DropdownContext = createContext<DropdownContextType | undefined>(undefined);

// 复合组件Props类型
type DropdownProps = {
  children: ReactNode;
  defaultValue?: string;
  onSelect?: (value: string) => void;
  className?: string;
};

type DropdownTriggerProps = {
  children: ReactNode;
  className?: string;
};

type DropdownMenuProps = {
  children: ReactNode;
  className?: string;
};

type DropdownItemProps = {
  children: ReactNode;
  value: string;
  className?: string;
};

// 主组件
export const Dropdown: React.FC<DropdownProps> = ({
  children,
  defaultValue = null,
  onSelect,
  className = ''
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const [selectedValue, setSelectedValue] = useState<string | null>(defaultValue);

  const toggle = () => setIsOpen(!isOpen);
  const close = () => setIsOpen(false);

  const handleSelect = (value: string) => {
    setSelectedValue(value);
    onSelect?.(value);
    close();
  };

  const contextValue: DropdownContextType = {
    isOpen,
    toggle,
    close,
    selectedValue,
    setSelectedValue: handleSelect
  };

  return (
    <div className={`dropdown ${className}`}>
      <DropdownContext.Provider value={contextValue}>
        {children}
      </DropdownContext.Provider>
    </div>
  );
};

// Trigger组件
export const DropdownTrigger: React.FC<DropdownTriggerProps> = ({
  children,
  className = ''
}) => {
  const context = useContext(DropdownContext);
  if (!context) {
    throw new Error('DropdownTrigger must be used within a Dropdown');
  }

  return (
    <button
      className={`dropdown-trigger ${className}`}
      onClick={context.toggle}
      aria-expanded={context.isOpen}
    >
      {children}
    </button>
  );
};

// Menu组件
export const DropdownMenu: React.FC<DropdownMenuProps> = ({
  children,
  className = ''
}) => {
  const context = useContext(DropdownContext);
  if (!context) {
    throw new Error('DropdownMenu must be used within a Dropdown');
  }

  return (
    <div
      className={`dropdown-menu ${context.isOpen ? 'open' : ''} ${className}`}
      onMouseLeave={context.close}
    >
      {children}
    </div>
  );
};

// Item组件
export const DropdownItem: React.FC<DropdownItemProps> = ({
  children,
  value,
  className = ''
}) => {
  const context = useContext(DropdownContext);
  if (!context) {
    throw new Error('DropdownItem must be used within a Dropdown');
  }

  const isSelected = context.selectedValue === value;

  const handleClick = () => {
    context.setSelectedValue(value);
  };

  return (
    <div
      className={`dropdown-item ${isSelected ? 'selected' : ''} ${className}`}
      onClick={handleClick}
      role="menuitem"
      aria-selected={isSelected}
    >
      {children}
    </div>
  );
};

// 导出复合组件
export default Object.assign(Dropdown, {
  Trigger: DropdownTrigger,
  Menu: DropdownMenu,
  Item: DropdownItem
});

使用示例:

// 页面中使用Dropdown复合组件
import Dropdown from '@components/common/Dropdown';

const MyPage = () => {
  const handleSelect = (value: string) => {
    console.log('Selected value:', value);
  };

  return (
    <div className="my-page">
      <h2>用户菜单</h2>
      <Dropdown onSelect={handleSelect} defaultValue="option2">
        <Dropdown.Trigger>
          选择选项
        </Dropdown.Trigger>
        <Dropdown.Menu>
          <Dropdown.Item value="option1">选项一</Dropdown.Item>
          <Dropdown.Item value="option2">选项二</Dropdown.Item>
          <Dropdown.Item value="option3">选项三</Dropdown.Item>
        </Dropdown.Menu>
      </Dropdown>
    </div>
  );
};

五、性能优化实战

5.1 构建优化配置

// vite.config.ts 中的性能优化配置
export default defineConfig({
  // ...其他配置
  build: {
    // 生产环境构建目标
    target: 'es2015',
    // 启用CSS代码分割
    cssCodeSplit: true,
    // 生产环境是否生成sourcemap
    sourcemap: false,
    // 启用rollup的treeshaking
    rollupOptions: {
      output: {
        // 代码分割配置
        manualChunks: {
          // 第三方库分割
          vendor: ['react', 'react-dom'],
          // UI组件库分割
          ui: ['@mui/material', '@mui/icons-material'],
          // 工具库分割
          utils: ['lodash', 'date-fns', 'axios'],
          // 图表库分割
          charts: ['recharts']
        },
        // 静态资源命名
        assetFileNames: 'assets/[ext]/[name]-[hash:8].[ext]',
        // 入口JS命名
        entryFileNames: 'js/[name]-[hash:8].js',
        // 代码分割JS命名
        chunkFileNames: 'js/[name]-[hash:8].js'
      }
    },
    // 关闭开发环境的计算
    reportCompressedSize: false,
    // 预构建依赖优化
    optimizeDeps: {
      include: [
        'react',
        'react-dom',
        'axios',
        'lodash-es'
      ],
      // 排除不需要预构建的依赖
      exclude: ['@mui/material']
    }
  }
});

5.2 懒加载实现

// 路由懒加载配置
// src/router/index.tsx
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Loading from '@components/common/Loading';
import ErrorPage from '@pages/ErrorPage';

// 使用React.lazy懒加载页面组件
const Home = React.lazy(() => import('@pages/Home'));
const About = React.lazy(() => import('@pages/About'));
const Products = React.lazy(() => import('@pages/Products'));
const ProductDetail = React.lazy(() => import('@pages/ProductDetail'));
const UserCenter = React.lazy(() => import('@pages/UserCenter'));

// 路由配置
const router = createBrowserRouter([
  {
    path: '/',
    element: (
      <React.Suspense fallback={<Loading />}>
        <Home />
      </React.Suspense>
    ),
    errorElement: <ErrorPage />
  },
  {
    path: '/about',
    element: (
      <React.Suspense fallback={<Loading />}>
        <About />
      </React.Suspense>
    )
  },
  {
    path: '/products',
    element: (
      <React.Suspense fallback={<Loading />}>
        <Products />
      </React.Suspense>
    )
  },
  {
    path: '/products/:id',
    element: (
      <React.Suspense fallback={<Loading />}>
        <ProductDetail />
      </React.Suspense>
    )
  },
  {
    path: '/user',
    element: (
      <React.Suspense fallback={<Loading />}>
        <UserCenter />
      </React.Suspense>
    )
  }
]);

export default function AppRouter() {
  return <RouterProvider router={router} />;
}

5.3 图片优化策略

// 图片组件优化
// src/components/common/OptimizedImage.tsx
import React, { useState } from 'react';
import './OptimizedImage.less';

type OptimizedImageProps = {
  src: string;
  alt: string;
  width?: number | string;
  height?: number | string;
  lazy?: boolean;
  placeholderColor?: string;
  className?: string;
};

const OptimizedImage: React.FC<OptimizedImageProps> = ({
  src,
  alt,
  width,
  height,
  lazy = true,
  placeholderColor = '#f0f0f0',
  className = ''
}) => {
  const [isLoaded, setIsLoaded] = useState(false);
  const [error, setError] = useState(false);

  // 处理图片加载成功
  const handleLoad = () => {
    setIsLoaded(true);
  };

  // 处理图片加载失败
  const handleError = () => {
    setError(true);
    setIsLoaded(true);
  };

  return (
    <div
      className={`optimized-image ${className} ${isLoaded ? 'loaded' : 'loading'}`}
      style={{
        width,
        height,
        backgroundColor: placeholderColor
      }}
    >
      {error ? (
        <div className="image-error">
          <span className="error-icon">!</span>
          <span className="error-text">图片加载失败</span>
        </div>
      ) : (
        <img
          src={src}
          alt={alt}
          loading={lazy ? 'lazy' : 'eager'}
          onLoad={handleLoad}
          onError={handleError}
          className={isLoaded ? 'visible' : 'hidden'}
        />
      )}
    </div>
  );
};

export default OptimizedImage;

5.4 性能监控与分析

// src/utils/performanceMonitor.ts
/**
 * 性能监控工具
 */
export class PerformanceMonitor {
  private startTime: number;
  private marks: Record<string, number>;
  private measures: Record<string, { start: string; end: string; duration: number }>;

  constructor() {
    this.startTime = performance.now();
    this.marks = {};
    this.measures = {};
  }

  /**
   * 创建性能标记
   * @param name 标记名称
   */
  mark(name: string): void {
    this.marks[name] = performance.now();
    performance.mark(name);
  }

  /**
   * 测量两个标记之间的时间差
   * @param name 测量名称
   * @param startMark 开始标记名称
   * @param endMark 结束标记名称
   * @returns 时间差(毫秒)
   */
  measure(name: string, startMark: string, endMark: string): number {
    if (!this.marks[startMark] || !this.marks[endMark]) {
      console.error(`Performance marks ${startMark} or ${endMark} not found`);
      return 0;
    }

    const duration = this.marks[endMark] - this.marks[startMark];
    this.measures[name] = {
      start: startMark,
      end: endMark,
      duration
    };

    performance.measure(name, startMark, endMark);
    return duration;
  }

  /**
   * 记录API请求性能
   * @param apiName API名称
   * @param duration 请求耗时(毫秒)
   */
  recordApiPerformance(apiName: string, duration: number): void {
    // 可以发送到监控服务器
    console.info(`API Performance: ${apiName} - ${duration.toFixed(2)}ms`);
    
    // 在生产环境可以发送到监控服务
    if (process.env.NODE_ENV === 'production') {
      // fetch('/api/monitor/performance', {
      //   method: 'POST',
      //   headers: { 'Content-Type': 'application/json' },
      //   body: JSON.stringify({
      //     type: 'api',
      //     name: apiName,
      //     duration,
      //     timestamp: Date.now()
      //   })
      // });
    }
  }

  /**
   * 获取所有性能数据
   */
  getAllData(): {
    totalTime: number;
    marks: Record<string, number>;
    measures: Record<string, { start: string; end: string; duration: number }>;
  } {
    return {
      totalTime: performance.now() - this.startTime,
      marks: { ...this.marks },
      measures: { ...this.measures }
    };
  }

  /**
   * 打印性能报告
   */
  printReport(): void {
    const report = this.getAllData();
    console.group('Performance Report');
    console.log('Total time:', report.totalTime.toFixed(2), 'ms');
    console.log('Marks:', report.marks);
    console.log('Measures:');
    Object.entries(report.measures).forEach(([name, data]) => {
      console.log(`  ${name}: ${data.duration.toFixed(2)}ms (${data.start} to ${data.end})`);
    });
    console.groupEnd();
  }
}

// 创建全局实例
export const performanceMonitor = new PerformanceMonitor();

六、CI/CD自动化部署

6.1 GitHub Actions配置文件

# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

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

jobs:
  # 代码检查和测试
  lint-and-test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        cache-dependency-path: package-lock.json
    
    - name: Install dependencies
      run: npm ci --registry=https://registry.npmmirror.com
    
    - name: Lint code
      run: npm run lint
    
    - name: Format check
      run: npm run format:check
    
    - name: Run unit tests
      run: npm run test:coverage
    
    - name: Upload coverage report
      uses: codecov/codecov-action@v3
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        file: ./coverage/coverage-final.json
        fail_ci_if_error: true

  # 构建项目
  build:
    needs: lint-and-test
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        cache-dependency-path: package-lock.json
    
    - name: Install dependencies
      run: npm ci --registry=https://registry.npmmirror.com
    
    - name: Build project
      run: npm run build
      
    - name: Upload build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: build-files
        path: ./dist

  # 部署到开发环境
  deploy-dev:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/develop'
    
    steps:
    - name: Download build artifacts
      uses: actions/download-artifact@v3
      with:
        name: build-files
        path: ./dist
    
    - name: Deploy to Dev Server
      uses: easingthemes/ssh-deploy@v2
      env:
        SSH_PRIVATE_KEY: ${{ secrets.DEV_SSH_KEY }}
        ARGS: "-rltgoDzvO --delete"
        SOURCE: "dist/"
        REMOTE_HOST: ${{ secrets.DEV_HOST }}
        REMOTE_USER: ${{ secrets.DEV_USER }}
        TARGET: "/var/www/dev.my-project.com"
    
    - name: Notify deployment
      uses: 8398a7/action-slack@v3
      with:
        status: ${{ job.status }}
        fields: repo,message,commit,author,action,eventName,ref,workflow
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
      if: always()

  # 部署到生产环境
  deploy-prod:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    environment: production  # 需要手动批准
    
    steps:
    - name: Download build artifacts
      uses: actions/download-artifact@v3
      with:
        name: build-files
        path: ./dist
    
    - name: Deploy to Production Server
      uses: easingthemes/ssh-deploy@v2
      env:
        SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_KEY }}
        ARGS: "-rltgoDzvO --delete"
        SOURCE: "dist/"
        REMOTE_HOST: ${{ secrets.PROD_HOST }}
        REMOTE_USER: ${{ secrets.PROD_USER }}
        TARGET: "/var/www/my-project.com"
    
    - name: Purge CDN Cache
      run: |
        curl -X POST "https://cdn.example.com/api/purge" \
          -H "Authorization: Bearer ${{ secrets.CDN_API_KEY }}" \
          -H "Content-Type: application/json" \
          -d '{"purgeAll": true}'
    
    - name: Notify deployment
      uses: 8398a7/action-slack@v3
      with:
        status: ${{ job.status }}
        fields: repo,message,commit,author,action,eventName,ref,workflow
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
      if: always()

6.2 部署流程示意图

mermaid

七、工程化架构模板使用指南

7.1 快速创建新项目

# 1. 克隆项目模板
git clone https://gitcode.com/GitHub_Trending/pr/Project-Ideas-And-Resources.git

# 2. 进入前端工程化模板目录
cd Project-Ideas-And-Resources/templates/frontend-engineering-react

# 3. 安装依赖
npm install --registry=https://registry.npmmirror.com

# 4. 启动开发服务器
npm run dev

# 5. 构建生产版本
npm run build

# 6. 运行单元测试
npm run test:unit

# 7. 提交代码
npm run commit

7.2 项目配置自定义

mermaid

八、前端工程化最佳实践清单

8.1 开发环境配置清单

  •  使用ESLint + Prettier保证代码风格一致
  •  配置Husky实现提交前代码检查
  •  使用Commitlint规范提交信息
  •  配置路径别名简化导入
  •  使用TypeScript增强类型安全
  •  配置开发环境代理解决跨域
  •  实现热更新提高开发效率

8.2 构建优化清单

  •  配置代码分割减小初始加载体积
  •  启用Tree-shaking移除未使用代码
  •  配置静态资源压缩(gzip/brotli)
  •  优化第三方依赖(预构建/CDN)
  •  配置生产环境sourcemap策略
  •  实现构建缓存加速构建过程
  •  配置静态资源CDN加速

8.3 性能优化清单

  •  实现路由懒加载
  •  使用React.memo/useMemo优化渲染
  •  实现图片懒加载和优化
  •  配置资源预加载和预连接
  •  实现大列表虚拟滚动
  •  优化关键渲染路径
  •  使用Web Workers处理复杂计算

8.4 质量保障清单

  •  编写单元测试(覆盖率>80%)
  •  实现E2E测试覆盖关键流程
  •  配置代码审查流程
  •  实现性能监控和上报
  •  配置错误监控和上报
  •  定期进行安全审计
  •  实现CI/CD自动化流程

结语

前端工程化是现代前端开发的基石,它不仅能显著提升开发效率,还能保障代码质量和系统性能。本文从架构设计、环境配置、开发规范、性能优化到CI/CD部署,全方位介绍了前端工程化的实践方案。随着前端技术的不断发展,工程化也在持续演进,建议开发者保持学习,不断优化和完善自己的工程化体系。

本文配套的前端工程化模板已同步至:https://gitcode.com/GitHub_Trending/pr/Project-Ideas-And-Resources

点赞+收藏+关注,获取更多前端工程化实战教程!下期预告:《微前端架构设计与实践》

附录:参考资源

【免费下载链接】Project-Ideas-And-Resources A Collection of application ideas that can be used to improve your coding skills ❤. 【免费下载链接】Project-Ideas-And-Resources 项目地址: https://gitcode.com/GitHub_Trending/pr/Project-Ideas-And-Resources

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值