跳转至

前端工程化

前端工程化

📚 章节目标

本章节将全面介绍前端工程化的核心技术和工具,包括 Webpack 、 Vite 、 Rollup 、模块化等,帮助学习者掌握前端工程化的核心方法。

学习目标

  1. 理解前端工程化的核心概念
  2. 掌握 Webpack 的深度配置
  3. 掌握 Vite 的构建优化
  4. 掌握 Rollup 的打包技术
  5. 理解模块化规范
  6. 掌握工程化最佳实践

🏗️ 前端工程化概述

1. 什么是前端工程化

JavaScript
// 前端工程化的核心要素
// 1. 模块化:将代码拆分成独立的模块
// 2. 组件化:将UI拆分成可复用的组件
// 3. 规范化:制定代码规范和项目规范
// 4. 自动化:自动化构建、测试、部署
// 5. 优化化:性能优化、代码优化

// 示例:模块化
// utils.js
export function formatDate(date) {
  return new Date(date).toLocaleDateString();
}

// main.js
import { formatDate } from './utils';
console.log(formatDate(new Date()));

// 示例:组件化
// Button.jsx
export function Button({ children, onClick }) {
  return <button onClick={onClick}>{children}</button>;
}

// App.jsx
import { Button } from './Button';

function App() {
  return <Button onClick={() => console.log('clicked')}>Click me</Button>;
}

2. 工程化工具链

JavaScript
// 前端工程化工具链
// 1. 包管理器:npm, yarn, pnpm
// 2. 构建工具:Webpack, Vite, Rollup
// 3. 代码规范:ESLint, Prettier
// 4. 测试工具:Jest, Cypress, Playwright
// 5. CI/CD:GitHub Actions, GitLab CI, Jenkins

// 示例:使用pnpm
pnpm install
pnpm add react
pnpm add -D typescript

// 示例:使用ESLint
npx eslint src/
npx eslint src/ --fix

// 示例:使用Prettier
npx prettier --write src/

📦 Webpack 深度配置

1. Webpack 基础

1.1 基本配置

JavaScript
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 入口文件
  entry: './src/index.js',

  // 输出配置
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },

  // 模式
  mode: 'production',

  // Loader配置
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.(png|jpg|jpeg|gif|svg)$/,
        type: 'asset/resource',
      },
    ],
  },

  // 插件配置
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
  ],
};

1.2 多入口配置

JavaScript
// webpack.config.js
module.exports = {
  entry: {
    main: './src/index.js',
    vendor: './src/vendor.js',
  },

  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
};

2. Loader 配置

2.1 JavaScript Loader

JavaScript
// babel-loader配置
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              '@babel/preset-react',
              '@babel/preset-typescript',
            ],
            plugins: [
              '@babel/plugin-transform-runtime',
              '@babel/plugin-transform-class-properties',
            ],
          },
        },
      },
    ],
  },
};

// .babelrc
{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not dead"]
      }
    }],
    "@babel/preset-react",
    "@babel/preset-typescript"
  ],
  "plugins": [
    "@babel/plugin-transform-runtime",
    "@babel/plugin-transform-class-properties"
  ]
}

2.2 CSS Loader

JavaScript
// CSS Loader配置
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader',
        ],
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
    ],
  },
};

// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer'),
    require('cssnano'),
  ],
};

2.3 CSS 现代特性(2024+)

随着浏览器对现代 CSS 特性的全面支持,以下特性已可在生产环境中使用:

CSS
/* 1. Container Queries - 容器查询(2023+ 全支持)*/
/* 允许根据父容器尺寸而非视口尺寸进行响应式设计 */
.card-container {
  container-type: inline-size;
  container-name: card;
}

/* 当容器宽度 >= 400px 时应用样式 */
@container card (min-width: 400px) {
  .card {
    display: flex;
    gap: 1rem;
  }
  .card-image {
    width: 40%;
  }
}

/* 2. CSS Nesting - 原生嵌套语法(2023+ 全支持)*/
/* 无需预处理器即可使用嵌套 */
.article {
  padding: 1rem;

  & h2 {
    font-size: 1.5rem;
    color: #333;
  }

  & p {
    line-height: 1.6;

    & a {
      color: blue;
      text-decoration: underline;
    }
  }

  /* 媒体查询也可嵌套 */
  @media (min-width: 768px) {
    padding: 2rem;
  }
}

/* 3. :has() 选择器 - 父选择器(2023+ 全支持)*/
/* CSS "父选择器",可根据子元素状态选择父元素 */

/* 选择包含 img 的 figure */
figure:has(img) {
  border: 1px solid #ddd;
}

/* 选择有 :checked 子元素的 label */
label:has(input:checked) {
  background-color: lightblue;
}

/* 选择相邻兄弟有 :invalid 的表单组 */
.form-group:has(+ .form-group input:invalid) {
  border-left: 3px solid red;
}

/* 4. subgrid - 子网格(2023+ 全支持)*/
.grid-parent {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

.grid-child {
  display: grid;
  grid-template-columns: subgrid; /* 继承父级的列轨道 */
  grid-column: span 3;
}

/* 5. @layer - 层叠层(2022+ 全支持)*/
/* 控制样式优先级,解决特异性问题 */
@layer reset, base, components, utilities;

@layer reset {
  * { margin: 0; padding: 0; }
}

@layer components {
  .btn { padding: 0.5rem 1rem; }
}

@layer utilities {
  .mt-4 { margin-top: 1rem !important; }
}

/* 6. color-mix() - 颜色混合(2023+ 全支持)*/
.button {
  --brand: #3b82f6;
  background: var(--brand);

  &:hover {
    /* 混合 20% 黑色实现暗化效果 */
    background: color-mix(in srgb, var(--brand), black 20%);
  }
}
JavaScript
// 现代 CSS 浏览器支持检测
const supportsContainerQueries = CSS.supports('container-type', 'inline-size');
const supportsNesting = CSS.supports('selector(&)');
const supportsHas = CSS.supports('selector(:has(*))');

console.log('Container Queries:', supportsContainerQueries); // true (Chrome 105+)
console.log('CSS Nesting:', supportsNesting);                // true (Chrome 120+)
console.log(':has() Selector:', supportsHas);                // true (Chrome 105+)

2.4 资源 Loader

JavaScript
// 资源Loader配置
module.exports = {
  module: {
    rules: [
      // 图片处理
      {
        test: /\.(png|jpg|jpeg|gif|svg|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024, // 8kb以下转base64
          },
        },
        generator: {
          filename: 'images/[name].[hash:6][ext]',
        },
      },
      // 字体处理
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name].[hash:6][ext]',
        },
      },
      // 媒体文件
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)$/,
        type: 'asset/resource',
        generator: {
          filename: 'media/[name].[hash:6][ext]',
        },
      },
    ],
  },
};

3. Plugin 配置

3.1 HTML Plugin

JavaScript
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
      filename: 'index.html',
      title: 'My App',
      minify: {
        collapseWhitespace: true,
        removeComments: true,
        removeRedundantAttributes: true,
        removeScriptTypeAttributes: true,
        useShortDoctype: true,
      },
    }),
  ],
};

3.2 清理插件

JavaScript
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  plugins: [
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: ['**/*', '!static-files/**'],
    }),
  ],
};

3.3 环境变量插件

JavaScript
const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
      'process.env.API_URL': JSON.stringify(process.env.API_URL),
    }),
  ],
};

4. 优化配置

4.1 代码分割

JavaScript
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10,
        },
        common: {
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true,
        },
      },
    },
    runtimeChunk: {
      name: 'runtime',
    },
  },
};

4.2 Tree Shaking

JavaScript
module.exports = {
  optimization: {
    usedExports: true,
    sideEffects: false,
    minimize: true,
  },
};

// package.json
{
  "sideEffects": false
}

4.3 压缩优化

JavaScript
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true,
            drop_debugger: true,
          },
        },
      }),
      new CssMinimizerPlugin(),
    ],
  },
};

⚡ Vite 构建优化

1. Vite 基础

1.1 基本配置

JavaScript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],

  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },

  server: {
    port: 3000,
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
  },

  build: {
    outDir: 'dist',
    assetsDir: 'assets',
    sourcemap: false,
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          router: ['react-router-dom'],
        },
      },
    },
  },
});

1.2 环境变量

JavaScript
// .env
VITE_API_URL=https://api.example.com

// .env.development
VITE_API_URL=http://localhost:8080

// .env.production
VITE_API_URL=https://api.example.com

// 在代码中使用
const apiUrl = import.meta.env.VITE_API_URL;

2. Vite 插件

2.1 常用插件

JavaScript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import vitePluginImp from 'vite-plugin-imp';
import legacy from '@vitejs/plugin-legacy';
import viteCompression from 'vite-plugin-compression';

export default defineConfig({
  plugins: [
    react(),

    // 按需引入
    vitePluginImp({
      libList: [
        {
          libName: 'antd',
          style: (name) => `antd/es/${name}/style`,
        },
      ],
    }),

    // 兼容旧浏览器
    legacy({
      targets: ['defaults', 'not IE 11'],
    }),

    // Gzip压缩
    viteCompression({
      verbose: true,
      disable: false,
      threshold: 10240,
      algorithm: 'gzip',
      ext: '.gz',
    }),
  ],
});

2.2 自定义插件

JavaScript
// vite.config.js
import { defineConfig } from 'vite';

function myPlugin() {
  return {
    name: 'my-plugin',
    transform(code, id) {
      if (id.endsWith('.js')) {
        // 转换代码
        return code.replace(/console\.log\(/g, 'logger.log(');
      }
    },
  };
}

export default defineConfig({
  plugins: [myPlugin()],
});

3. Vite 优化

3.1 依赖预构建

JavaScript
// vite.config.js
export default defineConfig({
  optimizeDeps: {
    include: ['react', 'react-dom'],
    exclude: ['your-custom-dep'],
  },
});

3.2 构建优化

JavaScript
// vite.config.js
export default defineConfig({
  build: {
    // 代码分割
    rollupOptions: {
      output: {
        manualChunks: (id) => {
          if (id.includes('node_modules')) {
            return id.toString().split('node_modules/')[1].split('/')[0].toString();
          }
        },
      },
    },

    // 压缩配置
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },

    // Chunk大小警告
    chunkSizeWarningLimit: 1000,
  },
});

⚡ Vite 6 新特性

版本说明: Vite 6 ( 2024 年末发布)引入 Environment API ,是该版本最重要的架构升级。

1. Environment API

TypeScript
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  // Vite 6 核心新特性:多 Environment 配置
  // 可同时处理 client / server(SSR)/ 自定义 Worker 环境
  environments: {
    client: {
      // 浏览器环境默认配置
      build: {
        outDir: 'dist/client',
      },
    },
    server: {
      // Node.js SSR 环境
      resolve: {
        // SSR 环境使用 node 导出条件
        conditions: ['node'],
        externalConditions: ['node'],
      },
      build: {
        outDir: 'dist/server',
      },
    },
    worker: {
      // Web Worker 专属环境
      webCompatible: true,
    },
  },

  plugins: [react()],
});

2. 在插件中使用 Environment API

TypeScript
// Environment API 让插件可以感知当前运行环境,实现差异化处理
import type { Plugin } from 'vite';

function myPlugin(): Plugin {
  return {
    name: 'my-env-aware-plugin',

    // resolveId 钩子现在可以访问 this.environment
    resolveId(id) {
      if (this.environment.name === 'client') {
        // 浏览器环境特定处理
        if (id === 'virtual:config') return id;
      }
      if (this.environment.name === 'server') {
        // SSR 环境特定处理
        if (id === 'virtual:server-config') return id;
      }
    },

    load(id) {
      if (id === 'virtual:config') {
        const ssr = this.environment.name !== 'client';
        return `export const isSSR = ${ssr};`;
      }
    },
  };
}

3. Vite 6 其他改进

TypeScript
// vite.config.ts
export default defineConfig({
  // 1. resolve.conditions 新增 'module' 和 'default' 条件支持
  resolve: {
    conditions: ['browser', 'module', 'import', 'default'],
  },

  build: {
    // 2. CSS 代码分割更智能(默认按使用方自动分割 CSS chunk)
    cssCodeSplit: true,

    // 3. 内置 Rollup 4 支持更好的 treeshaking 和更小的产物
    rollupOptions: {
      // Rollup 4 的 output.experimentalMinChunkSize(减少碎片化 chunk)
      output: {
        experimentalMinChunkSize: 10_000, // bytes
      },
    },
  },

  // 4. preview 命令新增 --outDir 参数支持多环境静态预览
  preview: {
    port: 5173,
  },

  // 5. 废弃提醒:Vite 6 移除了对 CommonJS API(createServer 等)
  //    从 CJS 模块引入的支持,需迁移到 ESM
});

// Vite 6 迁移注意事项
// - default import 了 Vite 配置需改用 ESM import(import { defineConfig } from 'vite')
// - sass-embedded 现在是 sass 的默认实现(旧 node-sass 不再支持)
// - this.environment.consumer 值从 'browser' 改为 'client'

� Turbopack

版本说明:Turbopack 在 Next.js 15 中正式稳定,已成为 next dev 的默认打包器。基于 Rust 的增量式打包引擎,大型项目下比 Webpack 快数倍到数十倍。

1. Turbopack 核心概念

Text Only
体系结构:
└── Turbopack(调度层)
    ├── Turbo Engine(增量计算引擎)
    │   ├── Task Graph(任务依赖图)
    │   ├── Cache Layer(函数级缓存)
    │   └── Parallel Execution(Rust async)
    ├── SWC(JS/TS 转译)
    └── 内置 CSS/资源处理

关键特性:
- 函数级缓存:仅重新计算已变更的函数输出(非文件级)
- 惰性计算:只构建当前请求的模块
- 跨进程缓存:持久化到磁盘,冷启动同样受益

2. 在 Next.js 15 中使用

Bash
# Next.js 15 中 turbopack 已成为 next dev 的默认引擎
npx next dev          # 默认使用 Turbopack
npx next dev --turbo  # 明确开启(与上一行等价)
npx next build        # 生产构建仍使用 Webpack(Turbopack 不支持 build)
JavaScript
// next.config.js——当前 Turbopack 配置项
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Next.js 15 中 turbopack 配置已移至顶层
  turbopack: {
    // 自定义路径别名(等同于 Webpack resolve.alias)
    resolveAlias: {
      '@components': './src/components',
      '@utils': './src/utils',
    },
    // 自定义文件扩展名解析顺序
    resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
    // 自定义 Loaders(命名规则跟 Webpack loaders 不同)
    rules: {
      '*.svg': {
        loaders: ['@svgr/webpack'],
        as: '*.js',
      },
      '*.mdx': {
        loaders: ['./my-mdx-loader.js'],
        as: '*.js',
      },
    },
  },
};

module.exports = nextConfig;

3. Turbopack vs Webpack vs Vite 性能对比

指标 Webpack 5 Vite 6 Turbopack
冷启动时间(大型项目) ~30-60s ~1-3s ~0.5-1s
HMR 速度 ~1-5s <100ms <50ms
内存占用 低(Rust)
跨进程缓存 ✅ filesystem cache ✅ persistent
完整生产构建 ❌(开发阶段)
生态成熟度 ✅ 成熟 ✅ 成熟 ⚠️ 发展中

⚠️ 使用确认:Turbopack 面向 Next.js 项目的开发阶段;独立项目依然推荐 Vite。Turborepo(构建流水线工具)与 Turbopack(模块打包工具)是两个独立的项目。


�🔄 Rollup 打包技术

1. Rollup 基础

1.1 基本配置

JavaScript
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import terser from '@rollup/plugin-terser';

export default {
  input: 'src/index.ts',
  output: [
    {
      file: 'dist/bundle.js',
      format: 'cjs',
      exports: 'auto',
    },
    {
      file: 'dist/bundle.esm.js',
      format: 'esm',
    },
    {
      file: 'dist/bundle.umd.js',
      format: 'umd',
      name: 'MyLibrary',
    },
  ],
  plugins: [
    resolve(),
    commonjs(),
    typescript(),
    terser(),
  ],
};

1.2 多入口配置

JavaScript
// rollup.config.js
export default {
  input: {
    main: 'src/index.ts',
    utils: 'src/utils/index.ts',
  },
  output: {
    dir: 'dist',
    format: 'esm',
    entryFileNames: '[name].js',
    chunkFileNames: '[name]-[hash].js',
  },
};

2. Rollup 插件

2.1 常用插件

JavaScript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import json from '@rollup/plugin-json';
import babel from '@rollup/plugin-babel';
import replace from '@rollup/plugin-replace';
import alias from '@rollup/plugin-alias';
import postcss from 'rollup-plugin-postcss';

export default {
  plugins: [
    // 路径别名
    alias({
      entries: [
        { find: '@', replacement: './src' },
      ],
    }),

    // 解析node_modules
    resolve({
      browser: true,
    }),

    // 转换CommonJS
    commonjs(),

    // TypeScript支持
    typescript(),

    // JSON支持
    json(),

    // Babel转译
    babel({
      babelHelpers: 'bundled',
      exclude: 'node_modules/**',
    }),

    // 环境变量替换
    replace({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
      preventAssignment: true,
    }),

    // PostCSS
    postcss(),
  ],
};

2.2 自定义插件

JavaScript
// rollup.config.js
function myPlugin(options = {}) {
  return {
    name: 'my-plugin',

    transform(code, id) {
      if (id.endsWith('.js')) {
        // 转换代码
        return {
          code: code.replace(/console\.log\(/g, 'logger.log('),
          map: null,
        };
      }
    },

    generateBundle(options, bundle) {
      // 生成bundle时执行
      console.log('Bundle generated');
    },
  };
}

export default {
  plugins: [myPlugin()],
};

3. Rollup 优化

3.1 Tree Shaking

JavaScript
// rollup.config.js
export default {
  treeshake: {
    moduleSideEffects: false,
    propertyReadSideEffects: false,
    unknownGlobalSideEffects: false,
  },
};

3.2 代码分割

JavaScript
// rollup.config.js
export default {
  output: {
    manualChunks: (id) => {  // 箭头函数:简洁的函数语法
      if (id.includes('node_modules')) {
        return 'vendor';
      }
    },
  },
};

📦 模块化规范

1. CommonJS

JavaScript
// 导出
// utils.js
function formatDate(date) {
  return new Date(date).toLocaleDateString();
}

function formatNumber(num) {
  return num.toLocaleString();
}

module.exports = {
  formatDate,
  formatNumber,
};

// 或者
exports.formatDate = formatDate;
exports.formatNumber = formatNumber;

// 导入
const { formatDate, formatNumber } = require('./utils');  // 解构赋值:从对象/数组提取值

// 或者
const utils = require('./utils');  // const不可重新赋值;let块级作用域变量
utils.formatDate(new Date());

2. ES Modules

JavaScript
// 导出
// utils.js
export function formatDate(date) {
  return new Date(date).toLocaleDateString();
}

export function formatNumber(num) {
  return num.toLocaleString();
}

// 默认导出
export default function logger(message) {
  console.log(message);
}

// 导入
import { formatDate, formatNumber } from './utils';
import logger from './logger';

// 或者
import * as utils from './utils';
utils.formatDate(new Date());

// 动态导入
button.addEventListener('click', async () => {  // async定义异步函数;await等待Promise完成
  const module = await import('./heavy-module.js');  // await等待异步操作完成
  module.doSomething();
});

3. UMD

JavaScript
// UMD模块
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(['exports'], factory);
  } else if (typeof exports === 'object') {
    // CommonJS
    factory(exports);
  } else {
    // Browser globals
    factory(root.myLibrary = {});
  }
}(this, function (exports) {
  exports.formatDate = function(date) {
    return new Date(date).toLocaleDateString();
  };

  exports.formatNumber = function(num) {
    return num.toLocaleString();
  };
}));

🛠️ 工程化最佳实践

1. 项目结构

Text Only
project/
├── public/              # 静态资源
│   ├── index.html
│   └── favicon.ico
├── src/                 # 源代码
│   ├── assets/          # 资源文件
│   ├── components/      # 组件
│   ├── pages/           # 页面
│   ├── services/        # 服务
│   ├── utils/           # 工具函数
│   ├── hooks/           # 自定义Hooks
│   ├── store/           # 状态管理
│   ├── router/          # 路由配置
│   ├── styles/          # 样式文件
│   └── index.js         # 入口文件
├── tests/               # 测试文件
├── .eslintrc.js        # ESLint配置
├── .prettierrc.js      # Prettier配置
├── .gitignore           # Git忽略文件
├── package.json         # 项目配置
└── README.md            # 项目说明

2. 代码规范

2.1 ESLint 配置

JavaScript
// .eslintrc.js
module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  plugins: ['react', '@typescript-eslint', 'prettier'],
  rules: {
    'react/react-in-jsx-scope': 'off',
    '@typescript-eslint/no-explicit-any': 'warn',
    'prettier/prettier': 'error',
  },
  settings: {
    react: {
      version: 'detect',
    },
  },
};

2.2 Prettier 配置

JavaScript
// .prettierrc.js
module.exports = {
  semi: true,
  singleQuote: true,
  tabWidth: 2,
  trailingComma: 'es5',
  printWidth: 80,
  arrowParens: 'always',
  endOfLine: 'lf',
};

3. Git 工作流

Bash
# 分支策略
# main - 主分支
# develop - 开发分支
# feature/* - 功能分支
# hotfix/* - 紧急修复分支

# 工作流程
# 1. 从develop创建功能分支
git checkout -b feature/new-feature

# 2. 开发并提交
git add .
git commit -m "feat: add new feature"

# 3. 推送到远程
git push origin feature/new-feature

# 4. 创建Pull Request

# 5. 代码审查

# 6. 合并到develop

# 7. 定期合并到main

4. CI/CD 配置

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

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

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Test
        run: npm test

      - name: Build
        run: npm run build

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v20
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.ORG_ID }}
          vercel-project-id: ${{ secrets.PROJECT_ID }}
          vercel-args: '--prod'

📝 练习题

1. 基础题

题目 1 :配置 Webpack 处理 TypeScript

JavaScript
// webpack.config.js
module.exports = {
  // 配置Webpack处理TypeScript
  module: {
    rules: [
      // 添加TypeScript loader
    ],
  },
};

2. 进阶题

题目 2 :配置 Vite 实现按需引入

JavaScript
// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    // 配置按需引入插件
  ],
});

3. 面试题

题目 3 :比较 Webpack 和 Vite 的区别

JavaScript
// 答案要点:
// 1. Webpack使用bundle模式,Vite使用ESM模式
// 2. Webpack冷启动慢,Vite冷启动快
// 3. Webpack热更新中等,Vite热更新快
// 4. Webpack配置复杂,Vite配置简单
// 5. Webpack生态成熟,Vite生态快速发展
// 6. Webpack适合所有项目,Vite适合现代项目

🎯 本章总结

本章节全面介绍了前端工程化的核心技术和工具,包括 Webpack 、 Vite 、 Rollup 、模块化等。关键要点:

  1. 工程化概念:理解前端工程化的核心要素
  2. Webpack:掌握 Webpack 的深度配置和优化
  3. Vite:掌握 Vite 的构建优化和插件
  4. Rollup:掌握 Rollup 的打包技术
  5. 模块化:理解 CommonJS 、 ES Modules 、 UMD 规范
  6. 最佳实践:掌握项目结构、代码规范、 Git 工作流、 CI/CD 配置

下一步将深入学习前端测试技术。