Skip to content
On this page

Webpack 性能优化

Webpack 性能优化是构建高效开发体验和生产环境的关键。本章将详细介绍如何优化 Webpack 的构建速度和输出质量。

构建性能优化

1. 启用缓存

javascript
module.exports = {
  cache: {
    type: 'filesystem',                    // 文件系统缓存
    buildDependencies: {
      config: [__filename]                 // 配置文件变更时清除缓存
    },
    cacheDirectory: path.resolve(__dirname, '.webpack-cache'),
    name: 'production'                     // 缓存名称
  },
  
  snapshot: {
    managedPaths: [                        // Webpack 监控的路径
      path.resolve(__dirname, 'node_modules')
    ],
    immutablePaths: [                      // 不变路径
      path.resolve(__dirname, 'immutable-deps')
    ]
  }
};

2. 优化模块解析

javascript
module.exports = {
  resolve: {
    // 优化模块解析
    modules: [
      path.resolve(__dirname, 'src'),      // 优先查找项目源码
      'node_modules'                       // 然后查找 node_modules
    ],
    
    // 减少扩展名尝试
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
    
    // 使用别名减少解析时间
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@utils': path.resolve(__dirname, 'src/utils')
    },
    
    // 解析时的主字段
    mainFields: ['browser', 'module', 'main'],
    
    // 解析目录时的主文件
    mainFiles: ['index']
  },
  
  // 排除不需要解析的模块
  module: {
    noParse: [
      /jquery/,                           // 不解析 jQuery
      /lodash/                            // 不解析 Lodash
    ]
  }
};

3. 并行处理优化

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

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: require('os').cpus().length,  // 使用所有 CPU 核心
        extractComments: false
      }),
      new CssMinimizerPlugin({
        parallel: require('os').cpus().length   // 并行处理 CSS
      })
    ]
  },
  
  // 使用 thread-loader 并行处理
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: 'thread-loader',
            options: {
              workers: require('os').cpus().length - 1
            }
          },
          'babel-loader'
        ],
        exclude: /node_modules/
      }
    ]
  }
};

开发环境性能优化

1. 选择合适的 devtool

javascript
// 开发环境配置
module.exports = {
  mode: 'development',
  devtool: 'eval-cheap-module-source-map', // 平衡构建速度和调试体验
  // devtool: 'eval'                      // 构建最快
  // devtool: 'eval-source-map'           // 调试最佳,但构建慢
};

2. 优化开发服务器配置

javascript
module.exports = {
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
      watch: {
        ignored: [
          path.join(__dirname, 'node_modules'),
          path.join(__dirname, '.git')
        ]
      }
    },
    hot: true,                            // 启用热模块替换
    liveReload: false,                    // 禁用页面自动刷新
    client: {
      overlay: false                      // 禁用错误覆盖层
    }
  }
};

3. 使用持久化缓存

javascript
module.exports = {
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename]
    },
    version: '1.0.0'                      // 缓存版本,变更时清除缓存
  }
};

生产环境性能优化

1. 代码分割优化

javascript
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: 10,
      maxAsyncRequests: 10,
      cacheGroups: {
        // 第三方库
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10,
          chunks: 'initial',
          maxSize: 244000
        },
        
        // React 生态
        react: {
          test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
          name: 'react',
          priority: 20,
          chunks: 'initial'
        },
        
        // 公共代码
        common: {
          name: 'common',
          minChunks: 2,
          priority: 5,
          chunks: 'initial',
          minSize: 0
        }
      }
    },
    
    // 运行时代码分离
    runtimeChunk: {
      name: 'runtime'
    }
  }
};

2. Tree Shaking 优化

javascript
module.exports = {
  mode: 'production',
  optimization: {
    sideEffects: false,                   // 正确标记副作用
    usedExports: true,                    // 启用标记使用的导出
    concatenateModules: true,             // 模块串联(Scope Hoisting)
    providedExports: true                 // 提供导出信息
  }
};

// 在 package.json 中标记副作用
// {
//   "sideEffects": [
//     "./src/polyfills.js",
//     "*.css"
//   ]
// }

3. 动态导入优化

javascript
// 在应用代码中使用动态导入
// src/components/LazyComponent.js
const LazyComponent = React.lazy(() => import('./HeavyComponent'));

// 预加载和预获取
const routes = [
  {
    path: '/dashboard',
    component: React.lazy(() => 
      import(/* webpackPreload: true */ './Dashboard')
    )
  },
  {
    path: '/profile',
    component: React.lazy(() => 
      import(/* webpackPrefetch: true */ './Profile')
    )
  }
];

资源优化

1. 图片和静态资源优化

javascript
module.exports = {
  module: {
    rules: [
      // Webpack 5 资源模块
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024              // 8kb 以下转为 base64
          }
        },
        generator: {
          filename: 'images/[name].[contenthash:8][ext]'
        }
      },
      
      // 字体文件
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name].[contenthash:8][ext]'
        }
      }
    ]
  }
};

2. 代码压缩优化

javascript
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true,            // 删除 console
            drop_debugger: true,           // 删除 debugger
            pure_funcs: ['console.log']    // 删除特定函数调用
          },
          mangle: {
            properties: {
              regex: /^__/                // 混淆以 __ 开头的属性
            }
          },
          format: {
            comments: false                // 删除注释
          }
        },
        extractComments: false
      })
    ]
  }
};

分析和监控

1. 构建分析

javascript
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    // 构建分析
    process.env.ANALYZE && new BundleAnalyzerPlugin({
      analyzerMode: process.env.NODE_ENV === 'production' ? 'static' : 'server',
      openAnalyzer: true,
      reportFilename: 'bundle-report.html'
    })
  ].filter(Boolean)
};

2. 性能监控

javascript
module.exports = {
  performance: {
    maxAssetSize: 250000,                 // 单个资源最大 250kb
    maxEntrypointSize: 250000,            // 入口点最大 250kb
    hints: 'warning'                      // 性能警告
  },
  
  stats: {
    all: false,
    modules: false,
    maxModules: 0,
    errors: true,
    warnings: true,
    assets: true,
    chunks: true,
    chunkModules: true
  }
};

高级优化技术

1. 模块联邦优化

javascript
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'shell',
      remotes: {
        mfe1: 'mfe1@http://localhost:3001/remoteEntry.js',
        mfe2: 'mfe2@http://localhost:3002/remoteEntry.js'
      },
      shared: {
        react: { singleton: true },
        'react-dom': { singleton: true }
      }
    })
  ]
};

2. 预加载和预获取

javascript
// 动态导入中的魔法注释
const Dashboard = React.lazy(() => 
  import(
    /* webpackChunkName: "dashboard" */
    /* webpackPreload: true */
    './Dashboard'
  )
);

const AdminPanel = React.lazy(() => 
  import(
    /* webpackChunkName: "admin" */
    /* webpackPrefetch: true */
    './AdminPanel'
  )
);

3. 条件加载

javascript
// 根据环境条件加载
const loadDevTools = async () => {
  if (process.env.NODE_ENV === 'development') {
    const { default: DevTools } = await import('./DevTools');
    return DevTools;
  }
  return null;
};

性能优化配置示例

javascript
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  mode: 'production',
  
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename]
    }
  },
  
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,
        terserOptions: {
          compress: {
            drop_console: true
          }
        }
      })
    ],
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10
        }
      }
    },
    runtimeChunk: 'single',
    moduleIds: 'deterministic',
    chunkIds: 'deterministic'
  },
  
  resolve: {
    modules: [
      path.resolve(__dirname, 'src'),
      'node_modules'
    ],
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components')
    }
  },
  
  plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css'
    })
  ],
  
  performance: {
    maxAssetSize: 250000,
    maxEntrypointSize: 250000,
    hints: 'warning'
  }
};

小结

Webpack 性能优化是一个持续的过程,需要根据项目特点和需求进行调整。关键优化点包括缓存配置、模块解析优化、代码分割、Tree Shaking、资源优化等。通过合理的配置和优化策略,可以显著提升构建速度和输出质量。