webpack 性能优化

43 阅读1分钟

1. 缩短构建时间

(1) 优化 Loader

使用 include 和 exclude 限定范围

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        include: /src/, // 仅处理 src 文件夹
        exclude: /node_modules/, // 排除 node_modules
      },
    ],
  },
};

使用缓存

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true, // 启用缓存
            },
          },
        ],
      },
    ],
  },
};
(2) 多线程/多进程打包

使用 thread-loader

npm install thread-loader --save-dev
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: 'thread-loader',
            options: {
              workers: 4, // 线程数量
            },
          },
          'babel-loader',
        ],
      },
    ],
  },
};

Terser 多线程压缩

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

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true, // 开启多线程
      }),
    ],
  },
};
(3) 缩小打包范围

使用 resolve.extensions 限制 Webpack 解析的文件扩展名

module.exports = {
  resolve: {
    extensions: ['.js', '.json'], // 仅解析指定类型
  },
};
使用 resolve.alias

通过别名优化模块查找路径。

module.exports = {
  resolve: {
    alias: {
      '@components': path.resolve(__dirname, 'src/components'),
    },
  },
};

优化模块查找路径,通过缩小模块查找范围提高速度

module.exports = {
  resolve: {
    modules: [path.resolve(__dirname, 'src'), 'node_modules'],
  },
};

2. 减小包体积

(1) 移除无用代码

Tree Shaking

  • 确保使用 ES6 模块 (import/export)。
  • 设置 sideEffects。
{
  "sideEffects": false
}
删除未使用的 CSS ,使用 purgecss-webpack-plugin 移除未使用的 CSS
npm install purgecss-webpack-plugin glob --save-dev
const PurgeCSSPlugin = require('purgecss-webpack-plugin');
const path = require('path');

module.exports = {
  plugins: [
    new PurgeCSSPlugin({
      paths: glob.sync(`${path.resolve(__dirname, 'src')}/**/*`, { nodir: true }),
    }),
  ],
};
(2) 按需加载 (Lazy Loading)

通过动态 import 按需加载模块。

const loadComponent = () => import('./MyComponent');
(3) 分离第三方依赖

SplitChunks 将第三方库打包到单独的文件中

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
};
(4) 压缩资源

使用 terser-webpack-plugin 压缩 JS

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

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
  },
};

使用 css-minimizer-webpack-plugin 压缩 CSS

npm install css-minimizer-webpack-plugin --save-dev
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  optimization: {
    minimizer: [new CssMinimizerPlugin()],
  },
};

使用 image-minimizer-webpack-plugin 压缩图片

npm install image-minimizer-webpack-plugin imagemin-mozjpeg imagemin-pngquant --save-dev
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new ImageMinimizerPlugin({
      minimizerOptions: {
        plugins: [
          ['mozjpeg', { quality: 75 }],
          ['pngquant', { quality: [0.65, 0.9] }],
        ],
      },
    }),
  ],
};

3. 提升运行时性能

(1) 持久化缓存

确保输出文件名包含哈希值,避免缓存问题。

module.exports = {
  output: {
    filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].js',
  },
};
(2) 预加载和预取资源

通过 webpack.PreloadPlugin 或 magic comments 实现资源预加载。

// 预加载
import(/* webpackPreload: true */ './module');

// 预取
import(/* webpackPrefetch: true */ './module');
(3) 使用 CDN

将第三方库通过 CDN 加载,减小包体积。

module.exports = {
  externals: {
    react: 'React',
    'react-dom': 'ReactDOM',
  },
};

在 HTML 中引入 CDN 资源:

<script src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"></script>

4. 分析与调试

(1) Bundle 分析

安装 webpack-bundle-analyzer。

npm install webpack-bundle-analyzer --save-dev
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
  plugins: [new BundleAnalyzerPlugin()],
};
(2) Source Map

便于调试,建议在生产环境使用 cheap-module-source-map。

module.exports = {
  devtool: 'cheap-module-source-map',
};