Webpack优化详解

Webpack 5提供了一系列工具和功能,可以在本地开发和线上构建过程中进行优化,以提高开发效率和构建性能。

1. 本地开发优化

1.1. 开启模块热替换(HMR)

模块热替换可以在不刷新整个页面的情况下更新模块,提高开发效率。

const webpack = require('webpack');

module.exports = {
  mode: 'development',
  devServer: {
    contentBase: './dist',
    hot: true,
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
  ],
};

1.2. 使用 Source Maps

Source Maps 有助于在浏览器中调试原始源代码,而不是转换后的代码。不同类型的 Source Maps 在性能和详细程度上有所不同。

module.exports = {
  mode: 'development',
  devtool: 'eval-source-map', // 'source-map' | 'cheap-module-source-map' | 'eval-source-map' 等
};

1.3. 优化编译速度

使用 cache 和 parallel 选项来加速构建过程。

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

module.exports = {
  mode: 'development',
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        cache: true,
        parallel: true,
        sourceMap: true,
      }),
    ],
  },
};

1.4. 使用持久化缓存

Webpack 5 提供了持久化缓存功能,可以显著提高重复构建的速度。

module.exports = {
  cache: {
    type: 'filesystem', // 使用文件系统缓存
  },
};

1.5. 更快的增量编译

配置 watchOptions 来优化文件监听,减少不必要的文件扫描。

module.exports = {
  watchOptions: {
    ignored: /node_modules/,
    aggregateTimeout: 300, // 防抖延迟
    poll: 1000, // 轮询时间
  },
};

2. 线上产物构建优化

2.1. 使用生产模式

生产模式下,Webpack 会自动启用各种优化,如压缩代码和启用 Tree Shaking。

module.exports = {
  mode: 'production',
};

2.2. 代码分割

使用代码分割技术,将代码拆分为多个文件,以便更好地利用浏览器缓存和加速加载速度。

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
};

2.3. 压缩 JavaScript

使用 TerserPlugin 压缩 JavaScript 代码。

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

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

2.4. 压缩 CSS

使用 css-minimizer-webpack-plugin 压缩 CSS 文件。

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

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      '...', // 保留默认的 minimizer
      new CssMinimizerPlugin(),
    ],
  },
};

2.5. 启用 Tree Shaking

Tree Shaking 可以移除未使用的代码,减小打包后的文件大小。确保使用 ES6 模块语法(import 和 export)。

module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true,
  },
};

2.6. 持久化缓存

配置持久化缓存,以便在后续构建中复用编译结果。

module.exports = {
  cache: {
    type: 'filesystem', // 使用文件系统缓存
    buildDependencies: {
      config: [__dirname], // 当配置文件变化时,缓存失效
    },
  },
};

2.7. Bundle 分析

使用 webpack-bundle-analyzer 插件可视化和分析打包结果,帮助发现和解决性能瓶颈。

const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

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

2.8. 懒加载和按需加载

使用动态 import() 语法实现懒加载和按需加载模块,优化首次加载时间。

// 在你的代码中
import(/* webpackChunkName: "my-chunk-name" */ './myModule').then(module => {
  // 使用模块
});

2.9. 压缩图片

使用 image-webpack-loader 压缩图片资源,减小文件大小,提高加载速度。

module.exports = {
  module: {
    rules: [
      {
        test: /.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: 'file-loader',
          },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
              // optipng.enabled: false will disable optipng
              optipng: {
                enabled: false,
              },
              pngquant: {
                quality: [0.65, 0.90],
                speed: 4,
              },
              gifsicle: {
                interlaced: false,
              },
              // the webp option will enable WEBP
              webp: {
                quality: 75,
              },
            },
          },
        ],
      },
    ],
  },
};

2.10. 内联 CSS 和 JavaScript

在某些情况下,将关键 CSS 和 JavaScript 内联到 HTML 中可以减少 HTTP 请求次数,提高加载速度。

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

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true,
        removeRedundantAttributes: true,
        removeScriptTypeAttributes: true,
        removeStyleLinkTypeAttributes: true,
        useShortDoctype: true,
      },
      inject: 'body',
    }),
  ],
};

3. 完整示例配置

3.1. 开发环境配置 

const webpack = require('webpack');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devtool: 'eval-source-map',
  devServer: {
    contentBase: './dist',
    hot: true,
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /.(png|jpe?g|gif|svg)$/,
        use: [
          {
            loader: 'file-loader',
          },
        ],
      },
    ],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
  ],
  optimization: {
    minimize: false,
  },
  cache: {
    type: 'filesystem',
  },
  watchOptions: {
    ignored: /node_modules/,
    aggregateTimeout: 300,
    poll: 1000,
  },
};

3.2. 生产环境配置 

const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /.(png|jpe?g|gif|svg)$/,
        use: [
          {
            loader: 'file-loader',
          },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
              optipng: {
                enabled: false,
              },
              pngquant: {
                quality: [0.65, 0.90],
                speed: 4,
              },
              gifsicle: {
                interlaced: false,
              },
              webp: {
                quality: 75,
              },
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true,
        removeRedundantAttributes: true,
        removeScriptTypeAttributes: true,
        removeStyleLinkTypeAttributes: true,
        useShortDoctype: true,
      },
      inject: 'body',
    }),
    new BundleAnalyzerPlugin(),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin(),
      new CssMinimizerPlugin(),
    ],
    splitChunks: {
      chunks: 'all',
    },
    usedExports: true,
  },
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__dirname],
    },
  },
};

通过以上配置,我们实现了 Webpack 5 针对本地开发和线上产物构建的详细优化策略。这些配置可以显著提高开发效率和构建性能,使项目在开发和生产环境中都能运行得更好。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容