Skip to content

Latest commit

 

History

History
1348 lines (1187 loc) · 32.4 KB

04-debugging-tools.md

File metadata and controls

1348 lines (1187 loc) · 32.4 KB

Next.js 16 现代调试工具完整指南

文档简介: Next.js 16 现代调试工具企业级应用指南,涵盖Chrome DevTools、VS Code调试、React DevTools、Next.js Debugger等现代调试工具链

目标读者: 具备基础调试知识的前端开发者,需要掌握企业级调试技巧和问题排查的工程师

前置知识: Next.js 16基础、TypeScript、JavaScript调试基础、浏览器开发者工具

预计时长: 6-8小时

文档信息(用途、难度与维护记录)

📚 文档元数据

属性 内容
模块 02-nextjs-frontend
分类 reference
难度 ⭐⭐⭐ (精通)
标签 #debugging #devtools #chrome-devtools #vscode-debug #react-devtools
更新日期 2026年9月
作者 Dev Quest Team
状态 ✅ 已完成

📚 概述

Next.js 16 企业级开发需要强大的调试工具链来快速定位和解决问题。本指南深入探讨现代调试工具的高级应用,涵盖性能分析、内存泄漏检测、网络请求调试、服务端调试等企业级调试场景,帮助开发团队建立高效的调试工作流。

🛠️ 企业级调试工具生态

调试工具分类体系

🔧 Webpack 配置

⚠️ Next.js 16 提示:Turbopack 已是默认打包器。以下 Webpack 自定义配置仅在迁移期通过 next dev --webpack / next build --webpack 显式启用时生效;新项目请优先使用顶层 turbopack 配置。

基础配置

Next.js 中的 Webpack 配置增强

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Webpack 配置增强
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    // 开发环境配置
    if (dev) {
      config.devtool = 'eval-source-map';

      // 热更新优化
      config.watchOptions = {
        poll: 1000,
        aggregateTimeout: 300,
        ignored: ['**/node_modules', '**/.next'],
      };
    }

    // 生产环境配置
    if (!dev && !isServer) {
      // 生产环境优化
      config.optimization = {
        ...config.optimization,
        splitChunks: {
          chunks: 'all',
          cacheGroups: {
            vendor: {
              test: /[\\/]node_modules[\\/]/,
              name: 'vendors',
              chunks: 'all',
            },
            common: {
              name: 'common',
              minChunks: 2,
              chunks: 'all',
              enforce: true,
            },
          },
        },
      };
    }

    // 解析配置
    config.resolve = {
      ...config.resolve,
      alias: {
        ...config.resolve.alias,
        '@': path.resolve(__dirname, 'src'),
        '@components': path.resolve(__dirname, 'src/components'),
        '@lib': path.resolve(__dirname, 'src/lib'),
        '@styles': path.resolve(__dirname, 'src/styles'),
      },
      extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
    };

    // 模块规则
    config.module.rules.push(
      // SVG 处理
      {
        test: /\.svg$/,
        use: [
          {
            loader: '@svgr/webpack',
            options: {
              svgo: true,
              svgoConfig: {
                plugins: [
                  {
                    name: 'preset-default',
                    params: {
                      overrides: {
                        removeViewBox: false,
                      },
                    },
                  },
                ],
              },
            },
          },
        ],
      },
      // Markdown 处理
      {
        test: /\.md$/,
        use: 'raw-loader',
      },
      // GLSL 着色器处理
      {
        test: /\.(glsl|vs|fs|vert|frag)$/,
        use: 'raw-loader',
      }
    );

    // 插件配置
    if (!isServer) {
      config.plugins.push(
        // Bundle Analyzer
        new (require('webpack-bundle-analyzer').BundleAnalyzerPlugin)({
          analyzerMode: 'disabled',
          openAnalyzer: false,
        })
      );
    }

    return config;
  },

};

module.exports = nextConfig;

高级 Webpack 配置

性能优化和高级特性

// webpack.config.js (独立使用)
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';
  const isDevelopment = !isProduction;

  return {
    mode: isProduction ? 'production' : 'development',

    entry: {
      main: './src/index.tsx',
      vendor: ['react', 'react-dom'],
    },

    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: isProduction
        ? 'js/[name].[contenthash].js'
        : 'js/[name].js',
      chunkFilename: isProduction
        ? 'js/[name].[contenthash].chunk.js'
        : 'js/[name].chunk.js',
      clean: true,
      publicPath: '/',
    },

    resolve: {
      extensions: ['.tsx', '.ts', '.jsx', '.js'],
      alias: {
        '@': path.resolve(__dirname, 'src'),
        react: 'preact/compat',
        'react-dom': 'preact/compat',
      },
    },

    module: {
      rules: [
        // TypeScript 处理
        {
          test: /\.tsx?$/,
          use: [
            {
              loader: 'ts-loader',
              options: {
                transpileOnly: isDevelopment,
                happyPackMode: true,
              },
            },
          ],
          exclude: /node_modules/,
        },

        // CSS 处理
        {
          test: /\.css$/,
          use: [
            isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
            {
              loader: 'css-loader',
              options: {
                modules: {
                  auto: true,
                  localIdentName: isDevelopment
                    ? '[name]__[local]--[hash:base64:5]'
                    : '[hash:base64:5]',
                },
              },
            },
            'postcss-loader',
          ],
        },

        // SCSS 处理
        {
          test: /\.scss$/,
          use: [
            isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
            'css-loader',
            'postcss-loader',
            {
              loader: 'sass-loader',
              options: {
                sourceMap: isDevelopment,
              },
            },
          ],
        },

        // 图片处理
        {
          test: /\.(png|jpg|jpeg|gif|webp)$/i,
          type: 'asset',
          parser: {
            dataUrlCondition: {
              maxSize: 8 * 1024, // 8kb
            },
          },
          generator: {
            filename: 'images/[name].[hash:8][ext]',
          },
        },

        // 字体处理
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/i,
          type: 'asset/resource',
          generator: {
            filename: 'fonts/[name].[hash:8][ext]',
          },
        },
      ],
    },

    plugins: [
      // HTML 模板
      new HtmlWebpackPlugin({
        template: './public/index.html',
        minify: isProduction ? {
          removeComments: true,
          collapseWhitespace: true,
          removeRedundantAttributes: true,
          useShortDoctype: true,
          removeEmptyAttributes: true,
          removeStyleLinkTypeAttributes: true,
          keepClosingSlash: true,
          minifyJS: true,
          minifyCSS: true,
          minifyURLs: true,
        } : false,
      }),

      // 环境变量
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development'),
        __DEV__: isDevelopment,
      }),

      // CSS 提取 (生产环境)
      ...(isProduction
        ? [
            new MiniCssExtractPlugin({
              filename: 'css/[name].[contenthash].css',
              chunkFilename: 'css/[name].[contenthash].chunk.css',
            }),
          ]
        : []),

      // 进度报告
      new webpack.ProgressPlugin(),
    ],

    optimization: {
      minimize: isProduction,
      minimizer: [
        // JS 压缩
        new TerserPlugin({
          parallel: true,
          terserOptions: {
            compress: {
              drop_console: isProduction,
              drop_debugger: isProduction,
            },
          },
        }),

        // CSS 压缩
        new CssMinimizerPlugin(),
      ],

      // 代码分割
      splitChunks: {
        chunks: 'all',
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendors',
            chunks: 'all',
            priority: 10,
          },
          common: {
            name: 'common',
            minChunks: 2,
            chunks: 'all',
            priority: 5,
            reuseExistingChunk: true,
          },
        },
      },

      // 运行时代码
      runtimeChunk: {
        name: 'runtime',
      },
    },

    // Source Maps
    devtool: isDevelopment ? 'eval-source-map' : 'source-map',

    // 开发服务器
    devServer: isDevelopment
      ? {
          hot: true,
          port: 3000,
          open: true,
          historyApiFallback: true,
          compress: true,
          client: {
            overlay: {
              errors: true,
              warnings: false,
            },
          },
        }
      : undefined,
  };
};

📦 Rollup 配置

基础 Rollup 配置

库和应用打包

// rollup.config.js
import { defineConfig } from 'rollup';
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import { terser } from 'rollup-plugin-terser';
import replace from '@rollup/plugin-replace';
import externalGlobals from 'rollup-plugin-external-globals';

const isProduction = process.env.NODE_ENV === 'production';

export default defineConfig([
  // UMD 构建
  {
    input: 'src/index.ts',
    output: {
      file: 'dist/index.umd.js',
      format: 'umd',
      name: 'MyLibrary',
      sourcemap: !isProduction,
    },
    plugins: [
      externalGlobals({
        react: 'React',
        'react-dom': 'ReactDOM',
      }),
      replace({
        'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development'),
        preventAssignment: true,
      }),
      resolve({
        browser: true,
        preferBuiltins: false,
      }),
      commonjs(),
      json(),
      typescript({
        declaration: true,
        declarationDir: 'dist/types',
        rootDir: 'src',
      }),
      ...(isProduction ? [terser()] : []),
    ],
    external: ['react', 'react-dom'],
  },

  // ES Modules 构建
  {
    input: 'src/index.ts',
    output: [
      {
        file: 'dist/index.esm.js',
        format: 'esm',
        sourcemap: !isProduction,
      },
      {
        file: 'dist/index.cjs.js',
        format: 'cjs',
        sourcemap: !isProduction,
      },
    ],
    plugins: [
      replace({
        'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development'),
        preventAssignment: true,
      }),
      resolve({
        browser: true,
      }),
      commonjs(),
      json(),
      typescript({
        declaration: false, // 已在 UMD 构建中生成
      }),
      ...(isProduction ? [terser()] : []),
    ],
    external: ['react', 'react-dom'],
  },
]);

高级 Rollup 配置

复杂项目构建配置

// rollup.config.js
import { defineConfig } from 'rollup';
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import alias from '@rollup/plugin-alias';
import { terser } from 'rollup-plugin-terser';
import { visualizer } from 'rollup-plugin-visualizer';
import filesize from 'rollup-plugin-filesize';
import progress from 'rollup-plugin-progress';
import replace from '@rollup/plugin-replace';
import image from '@rollup/plugin-image';
import postcss from 'rollup-plugin-postcss';

const isProduction = process.env.NODE_ENV === 'production';

const createConfig = (input, output, additionalPlugins = []) => ({
  input,
  output,
  plugins: [
    // 进度显示
    progress(),

    // 环境变量替换
    replace({
      'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development'),
      'process.env.VERSION': JSON.stringify(process.env.npm_package_version),
      preventAssignment: true,
    }),

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

    // 模块解析
    resolve({
      browser: true,
      preferBuiltins: false,
      dedupe: ['react', 'react-dom'],
    }),

    // CommonJS 支持
    commonjs({
      include: /node_modules/,
    }),

    // JSON 支持
    json(),

    // TypeScript
    typescript({
      tsconfig: './tsconfig.json',
      declaration: true,
      declarationDir: './dist/types',
      rootDir: './src',
    }),

    // PostCSS
    postcss({
      plugins: [
        require('tailwindcss'),
        require('autoprefixer'),
        ...(isProduction ? [require('cssnano')] : []),
      ],
      inject: true,
      extract: true,
    }),

    // 图片处理
    image({
      include: ['**/*.png', '**/*.jpg', '**/*.jpeg', '**/*.gif', '**/*.svg'],
      limit: 8192, // 8kb
    }),

    // 额外插件
    ...additionalPlugins,

    // 生产环境插件
    ...(isProduction
      ? [
          terser({
            compress: {
              drop_console: true,
              drop_debugger: true,
              pure_funcs: ['console.log'],
            },
            mangle: {
              reserved: ['React', 'ReactDOM'],
            },
          }),
          visualizer({
            filename: 'dist/stats.html',
            open: true,
            gzipSize: true,
          }),
        ]
      : []),

    // 文件大小报告
    filesize(),
  ],

  // 外部依赖
  external: (id) => {
    // 排除外部依赖
    return /^react|react-dom/.test(id);
  },

  // 优化
  treeshake: {
    moduleSideEffects: false,
    propertyReadSideEffects: false,
    unknownGlobalSideEffects: false,
  },
});

export default defineConfig([
  // 主库构建
  createConfig(
    'src/index.ts',
    [
      {
        file: 'dist/index.esm.js',
        format: 'esm',
        sourcemap: true,
      },
      {
        file: 'dist/index.cjs.js',
        format: 'cjs',
        sourcemap: true,
      },
    ]
  ),

  // 测试构建
  createConfig(
    'src/test-utils.ts',
    {
      file: 'dist/test-utils.esm.js',
      format: 'esm',
      sourcemap: true,
    }
  ),

  // UMD 构建
  createConfig(
    'src/index.ts',
    {
      file: 'dist/index.umd.js',
      format: 'umd',
      name: 'MyLibrary',
      sourcemap: true,
    },
    [
      // UMD 特定插件
      {
        name: 'bundle-umd',
        generateBundle(options, bundle) {
          // UMD 特定处理
        },
      },
    ]
  ),
]);

⚡ Esbuild 配置

基础 Esbuild 配置

极速构建工具配置

// esbuild.config.js
const esbuild = require('esbuild');
const path = require('path');

const isProduction = process.env.NODE_ENV === 'production';

const baseConfig = {
  entryPoints: ['src/index.tsx'],
  bundle: true,
  sourcemap: !isProduction,
  minify: isProduction,
  target: ['es2020', 'chrome58', 'firefox57', 'safari11'],
  format: 'esm',
 outdir: 'dist',
  define: {
    'process.env.NODE_ENV': `"${isProduction ? 'production' : 'development'}"`,
    'process.env.VERSION': `"${process.env.npm_package_version}"`,
  },
  loader: {
    '.tsx': 'tsx',
    '.ts': 'ts',
    '.jsx': 'jsx',
    '.js': 'js',
    '.json': 'json',
    '.css': 'css',
    '.png': 'dataurl',
    '.svg': 'text',
    '.woff': 'dataurl',
    '.woff2': 'dataurl',
  },
  external: ['react', 'react-dom'],
  splitting: true,
  chunkNames: 'chunk-[name]-[hash]',
  assetNames: 'assets/[name]-[hash]',
  logLevel: 'info',
};

async function build() {
  try {
    // 开发构建
    if (!isProduction) {
      const context = await esbuild.context({
        ...baseConfig,
        format: 'esm',
        banner: {
          js: '(() => new EventSource("/esbuild").onmessage = () => location.reload())();',
        },
      });

      await context.rebuild();
      await context.watch();
      console.log('Watching for changes...');
    } else {
      // 生产构建
      await esbuild.build({
        ...baseConfig,
        format: 'esm',
        drop: isProduction ? ['console', 'debugger'] : [],
      });

      // CJS 构建
      await esbuild.build({
        ...baseConfig,
        format: 'cjs',
        outfile: 'dist/index.cjs.js',
      });

      console.log('Build completed!');
    }
  } catch (error) {
    console.error('Build failed:', error);
    process.exit(1);
  }
}

build();

高级 Esbuild 配置

复杂项目构建

// esbuild.config.js
const esbuild = require('esbuild');
const path = require('path');
const fs = require('fs');

const isProduction = process.env.NODE_ENV === 'production';
const isWatch = process.argv.includes('--watch');

// 插件系统
const esbuildPlugins = [
  // 自定义 CSS 插件
  {
    name: 'css-modules',
    setup(build) {
      build.onResolve({ filter: /\.module\.css$/ }, (args) => ({
        path: args.path,
        namespace: 'css-module',
      }));

      build.onLoad({ filter: /\.css$/, namespace: 'css-module' }, async (args) => {
        const source = await fs.promises.readFile(args.path, 'utf8');
        const contents = `export default \`${source.replace(/`/g, '\\`')}\`;`;
        return { contents, loader: 'js' };
      });
    },
  },

  // SVG 插件
  {
    name: 'svg',
    setup(build) {
      build.onResolve({ filter: /\.svg$/ }, (args) => ({
        path: args.path,
        namespace: 'svg',
      }));

      build.onLoad({ filter: /\.svg$/, namespace: 'svg' }, async (args) => {
        const source = await fs.promises.readFile(args.path, 'utf8');
        const contents = `export default \`${source}\`;`;
        return { contents, loader: 'js' };
      });
    },
  },
];

// 构建配置
const buildConfig = {
  // 开发服务器
  ...(isWatch && {
    logLevel: 'info',
    banner: {
      js: `
        (() => {
          const eventSource = new EventSource('/esbuild');
          eventSource.onmessage = () => location.reload();
        })();
      `,
    },
  }),

  // 生产优化
  ...(isProduction && {
    minify: true,
    drop: ['console', 'debugger'],
    treeShaking: true,
    legalComments: 'none',
  }),

  // 共享配置
  entryPoints: [
    'src/index.tsx',
    'src/styles/main.css',
  ],
  bundle: true,
  sourcemap: !isProduction,
  target: ['es2020', 'chrome58', 'firefox57', 'safari11'],
  format: 'esm',
  mainFields: ['browser', 'module', 'main'],
  conditions: ['browser', 'default'],
  outdir: 'dist',
  loader: {
    '.tsx': 'tsx',
    '.ts': 'ts',
    '.jsx': 'jsx',
    '.js': 'js',
    '.json': 'json',
    '.css': 'css',
  },
  define: {
    'process.env.NODE_ENV': `"${isProduction ? 'production' : 'development'}"`,
    'process.env.VERSION': `"${process.env.npm_package_version}"`,
  },
  external: [
    'react',
    'react-dom',
    // 排除 Node.js 内置模块
    ...['fs', 'path', 'os', 'crypto', 'http', 'https', 'url', 'util'],
  ],
  splitting: true,
  chunkNames: 'chunk-[name]-[hash]',
  assetNames: 'assets/[name]-[hash]',
  plugins: esbuildPlugins,
  metafile: true,
};

async function build() {
  try {
    // 开发模式
    if (isWatch) {
      const context = await esbuild.context(buildConfig);
      await context.watch();
      console.log('Watching for changes...');

      // 启动开发服务器
      const { startServer } = require('esbuild-dev-server');
      const server = await startServer(
        esbuild.serve(
          {
            servedir: 'dist',
            port: 3000,
          },
          buildConfig
        )
      );
      console.log(`Development server running at http://localhost:${server.port}`);
    } else {
      // 生产构建
      const result = await esbuild.build(buildConfig);

      // 生成分析报告
      if (result.metafile) {
        fs.writeFileSync('dist/metafile.json', JSON.stringify(result.metafile, null, 2));
      }

      console.log('Build completed!');

      // 输出构建统计
      const { outputFiles } = result;
      const totalSize = outputFiles.reduce((sum, file) => sum + file.contents.byteLength, 0);
      console.log(`Total bundle size: ${(totalSize / 1024).toFixed(2)} KB`);
    }
  } catch (error) {
    console.error('Build failed:', error);
    process.exit(1);
  }
}

build();

🚀 SWC 配置

SWC 配置

Rust 编译器配置

// .swcrc
{
  "$schema": "https://json.schemastore.org/swcrc",
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true,
      "decorators": true,
      "dynamicImport": true
    },
    "transform": {
      "react": {
        "runtime": "automatic",
        "development": false,
        "refresh": false,
        "importSource": {
          "moduleName": "@emotion/react",
          "defaultImport": "styled"
        }
      },
      "optimizer": {
        "globals": {
          "vars": {
            "process.env.NODE_ENV": "production"
          }
        }
      }
    },
    "target": "es2020",
    "loose": false,
    "externalHelpers": false,
    "keepClassNames": false,
    "baseUrl": "./src",
    "paths": {
      "@/*": ["*"],
      "@components/*": ["components/*"],
      "@lib/*": ["lib/*"]
    }
  },
  "module": {
    "type": "es6",
    "strict": true,
    "strictMode": true,
    "lazy": false,
    "noInterop": false
  },
  "minify": true,
  "env": {
    "targets": {
      "browsers": ["> 0.25%", "not dead"]
    },
    "coreJs": "3.30",
    "mode": "entry",
    "debug": false
  },
  "isModule": true,
  "sourceMaps": true,
  "inlineSourcesContent": false
}

Next.js SWC 集成

在 Next.js 中使用 SWC

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // 启用 SWC
  experimental: {
    swcPlugins: [
      // SWC 插件配置
      ['@swc/plugin-emotion', {
        // Emotion 插件选项
      }],
      ['@swc/plugin-styled-components', {
        // Styled Components 插件选项
        displayName: true,
        ssr: true,
      }],
    ],
  },

  // SWC 配置

  // 自定义 SWC 配置
  compiler: {
    removeConsole: process.env.NODE_ENV === 'production',
    styledComponents: true,
    emotion: true,
  },

  // React 严格模式
  reactStrictMode: true,
};

module.exports = nextConfig;

🔧 构建工具对比

性能对比

不同构建工具的性能特点

// 构建工具性能对比
interface BuildToolComparison {
  webpack: {
    speed: 'Medium';
    ecosystem: 'Mature';
    configuration: 'Complex but flexible';
    features: [
      'Code splitting',
      'Tree shaking',
      'Hot module replacement',
      'Extensive plugin ecosystem',
      'Asset optimization'
    ];
    bestFor: 'Complex applications, enterprise projects';
  };

  rollup: {
    speed: 'Fast';
    ecosystem: 'Growing';
    configuration: 'Simple and focused';
    features: [
      'Tree shaking',
      'Code splitting',
      'Plugin system',
      'Format preservation',
      'Library friendly'
    ];
    bestFor: 'Libraries, smaller applications';
  };

  esbuild: {
    speed: 'Very Fast';
    ecosystem: 'Basic';
    configuration: 'Minimal';
    features: [
      'Extreme speed',
      'Built-in bundling',
      'TypeScript support',
      'CSS handling',
      'Tree shaking'
    ];
    bestFor: 'Fast builds, development tools';
  };

  swc: {
    speed: 'Very Fast';
    ecosystem: 'Growing';
    configuration: 'Simple';
    features: [
      'Rust-based compilation',
      'TypeScript support',
      'Minification',
      'Plugin system',
      'Next.js integration'
    ];
    bestFor: 'Next.js applications, fast compilation';
  };
}

// 构建时间基准 (相对值)
const buildTimeBenchmarks = {
  webpack: 1.0,     // 基准
  rollup: 0.8,      // 比Webpack快20%
  esbuild: 0.2,     // 比Webpack快5倍
  swc: 0.1,         // 比Webpack快10倍
};

// 包大小优化
const bundleSizeOptimization = {
  webpack: 'Good',
  rollup: 'Excellent',
  esbuild: 'Good',
  swc: 'Good',
};

选择指南

根据项目需求选择构建工具

// 构建工具选择指南
interface BuildToolSelection {
  projectType: {
    library: ['Rollup', 'Webpack'];
    application: ['Webpack', 'Vite', 'Next.js'];
    monorepo: ['Turborepo', 'Nx', 'Lerna'];
    componentLibrary: ['Rollup', 'Storybook'];
  };

  teamSize: {
    small: ['Vite', 'Esbuild', 'Rollup'];
    medium: ['Webpack', 'Rollup', 'Vite'];
    large: ['Webpack', 'Turborepo', 'Nx'];
  };

  performance: {
    critical: ['Esbuild', 'SWC', 'Turbopack'];
    moderate: ['Rollup', 'Vite'];
    flexible: ['Webpack'];
  };

  ecosystem: {
    mature: ['Webpack', 'Rollup'];
    growing: ['Vite', 'SWC'];
    basic: ['Esbuild'];
  };
}

// 决策矩阵
const decisionMatrix = {
  // 新项目,需要快速开发
  'New project, rapid development': {
    primary: 'Vite',
    alternatives: ['Next.js', 'Esbuild'],
    reasoning: 'Fast development server, minimal configuration',
  },

  // 组件库
  'Component library': {
    primary: 'Rollup',
    alternatives: ['Webpack', 'Vite'],
    reasoning: 'Excellent tree shaking, multiple format output',
  },

  // 大型企业应用
  'Enterprise application': {
    primary: 'Webpack',
    alternatives: ['Turborepo', 'Nx'],
    reasoning: 'Mature ecosystem, extensive plugin support',
  },

  // Next.js 项目
  'Next.js application': {
    primary: 'Turbopack (Next.js 16 默认)',
    alternatives: ['Webpack (--webpack 回退)', 'SWC'],
    reasoning: 'Built-in integration, default bundler since Next.js 16',
  },
};

📊 构建优化

代码分割策略

优化包大小和加载性能

// Webpack 代码分割
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 20000,
      maxSize: 244000,
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      automaticNameDelimiter: '~',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          priority: 10,
          reuseExistingChunk: true,
        },
        react: {
          test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
          priority: 20,
          name: 'react',
        },
        common: {
          name: 'common',
          minChunks: 2,
          priority: 5,
          chunks: 'initial',
          reuseExistingChunk: true,
        },
      },
    },
  },
};

// Rollup 代码分割
export default {
  input: {
    main: 'src/index.js',
    vendor: ['react', 'react-dom'],
  },
  output: {
    dir: 'dist',
    format: 'es',
    manualChunks(id) {
      if (id.includes('node_modules')) {
        return 'vendor';
      }
    },
  },
  plugins: [
    {
      name: 'split-manual',
      generateBundle(options, bundle) {
        // 自定义分割逻辑
      },
    },
  ],
};

缓存策略

优化构建缓存

// Webpack 缓存配置
module.exports = {
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename],
    },
    name: 'production-cache',
    version: '1.0.0',
  },
};

// Esbuild(注意:esbuild 无持久缓存选项,增量构建仅靠进程内缓存)
const esbuild = require('esbuild');

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  outfile: 'dist/bundle.js',
});

📋 最佳实践

构建排查先区分源码解析、依赖解析、打包与运行错误,保留实际命令、版本和第一条相关诊断。source map 把产物位置对应到源码,生产是否公开应按调试与信息暴露需求安排。

tree shaking、动态导入和压缩解决不同问题,也不保证所有未调用代码都会自动移除。构建提速用冷缓存与热缓存分别测量,避免缓存掩盖真实依赖。插件与构建脚本会执行代码,凭据和权限需限制;最终产物完整性不能由“构建成功”单独证明。

📖 总结

现代构建工具为前端开发提供了强大的能力:

Webpack:

  • 优势: 生态成熟、配置灵活、功能全面
  • 适用: 复杂应用、企业项目
  • 特点: 插件丰富、功能强大、学习曲线较高

Rollup:

  • 优势: 输出简洁、Tree shaking优秀、库友好
  • 适用: 组件库、包开发
  • 特点: 配置简单、输出优化、ES模块友好

Esbuild:

  • 优势: 极速构建、内置功能、零配置
  • 适用: 快速开发、工具链
  • 特点: 速度快、体积小、Golang编写

SWC:

  • 优势: Rust编译器、Next.js集成、TypeScript支持
  • 适用: Next.js项目、性能敏感应用
  • 特点: 编译快、内存效率高、渐进式

选择建议:

  1. 新项目: 优先考虑 Vite 或 Next.js
  2. 组件库: 使用 Rollup
  3. 大型应用: 使用 Webpack 或 Turbopack
  4. 性能要求: 考虑 Esbuild 或 SWC

🔄 文档交叉引用

相关文档

参考章节


📝 总结

核心要点回顾

  1. 构建工具选择: Webpack(成熟生态) → Rollup(库打包) → Esbuild(极速构建) → SWC(Next.js集成)的选择策略
  2. Webpack配置: 代码分割、插件系统、优化配置的企业级实践
  3. 性能优化: 缓存策略、并行构建、Tree Shaking的完整优化方案
  4. 开发体验: 热更新、Source Maps、错误处理的开发环境配置
  5. 工具集成: TypeScript、CSS处理器、测试工具的无缝集成方案

学习成果检查

  • 能够选择适合项目需求的构建工具并配置基础环境
  • 掌握Webpack的高级配置和性能优化技巧
  • 熟练使用Rollup进行库开发和模块打包
  • 能够配置Esbuild和SWC获得极致的构建性能
  • 理解构建工具的生态系统和最佳实践

🤝 贡献与反馈

内容改进

如果你发现本文档有改进空间,欢迎:

  • 🐛 报告问题: 在Issues中提出具体问题
  • 💡 建议改进: 提出修改建议和补充内容
  • 📝 参与贡献: 提交PR完善文档内容

学习反馈

分享你的学习体验:

  • ✅ 有用内容: 哪些部分对你最有帮助
  • ❓ 疑问点: 哪些内容需要进一步澄清
  • 🎯 建议: 希望增加什么内容

🔗 外部资源

官方文档

快速参考


文档状态: ✅ 已完成 | 🚧 进行中 | 📋 计划中 最后更新: 2026年9月 版本: v1.0.0

阅读导航

本模块理解地图 · 完整目录与版本 · 通用术语