打包体积减少 80%!Webpack 极致优化全攻略

文章目录

打包体积减少 80%!Webpack 极致优化全攻略

1. Webpack 基础概念与核心价值

1.1 什么是 Webpack?

Webpack 是一个现代 JavaScript 应用程序的静态模块打包器,它能够将各种资源(JS、CSS、图片、字体等)转换为依赖图并进行优化打包。

1.2 核心概念

  • Entry(入口):构建的起始点
  • Output(输出):打包后文件的存放位置
  • Loaders(加载器):处理非 JS 文件
  • Plugins(插件):执行更广泛的任务
  • Mode(模式):开发或生产环境
  • Module(模块):项目中的每个文件都是模块

2. 环境搭建与第一个配置

2.1 安装与初始化

# 创建项目目录
mkdir webpack-project && cd webpack-project

# 初始化 package.json
npm init -y

# 安装 webpack
npm install --save-dev webpack webpack-cli webpack-dev-server

# 查看版本
npx webpack --version

2.2 基础项目结构

webpack-project/
├── src/
│   ├── index.js
│   ├── utils.js
│   └── styles/
├── public/
│   └── index.html
├── dist/
├── webpack.config.js
└── package.json

2.3 第一个配置文件

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

module.exports = {
  // 入口文件
  entry: './src/index.js',
  
  // 输出配置
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.[contenthash].js',
    clean: true, // 清理输出目录
  },
  
  // 模式
  mode: 'development',
  
  // 开发服务器
  devServer: {
    static: './dist',
    port: 3000,
    hot: true,
    open: true,
  },
  
  // 插件
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
      title: 'Webpack App',
    }),
  ],
};

3. 核心配置深度解析

3.1 多入口配置

module.exports = {
  entry: {
    main: './src/index.js',
    admin: './src/admin.js',
    vendor: './src/vendor.js'
  },
  
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].bundle.js',
    chunkFilename: '[name].[contenthash].chunk.js',
  },
};

3.2 环境变量配置

// webpack.config.js
const webpack = require('webpack');

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';
  
  return {
    mode: isProduction ? 'production' : 'development',
    
    plugins: [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(argv.mode),
        'process.env.API_URL': JSON.stringify(
          isProduction ? 'https://api.prod.com' : 'https://api.dev.com'
        ),
      }),
    ],
  };
};

4. 加载器(Loaders)完全指南

4.1 常用 Loaders 配置

module.exports = {
  module: {
    rules: [
      // JavaScript/TypeScript
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react'],
          },
        },
      },
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      
      // 样式文件
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader', 'postcss-loader'],
      },
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
          'sass-loader',
        ],
      },
      
      // 资源文件
      {
        test: /\.(png|jpg|jpeg|gif|svg)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name].[contenthash][ext]',
        },
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name].[contenthash][ext]',
        },
      },
    ],
  },
};

4.2 自定义 Loader 开发

// loaders/simple-loader.js
module.exports = function(source) {
  console.log('Processing file:', this.resourcePath);
  
  // 简单的字符串替换
  const result = source.replace(/console\.log\(.*\);/g, '');
  
  // 可以返回多个结果
  this.callback(null, result, sourceMaps, ast);
  
  // 或者直接返回
  // return result;
};

5. 插件(Plugins)高级应用

5.1 常用插件配置

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');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
      minify: isProduction,
      inject: 'body',
    }),
    
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css',
      chunkFilename: 'css/[id].[contenthash].css',
    }),
    
    // 打包分析
    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      openAnalyzer: false,
    }),
    
    // 自定义插件示例
    function() {
      this.hooks.done.tap('CustomPlugin', (stats) => {
        console.log('构建完成!');
      });
    },
  ],
  
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: true,
        terserOptions: {
          compress: {
            drop_console: true,
          },
        },
      }),
      new CssMinimizerPlugin(),
    ],
  },
};

5.2 自定义插件开发

// plugins/simple-plugin.js
class SimpleWebpackPlugin {
  constructor(options) {
    this.options = options || {};
  }
  
  apply(compiler) {
    compiler.hooks.compilation.tap('SimplePlugin', (compilation) => {
      compilation.hooks.optimizeChunkAssets.tapAsync(
        'SimplePlugin',
        (chunks, callback) => {
          console.log('开始优化 chunks...');
          callback();
        }
      );
    });
    
    compiler.hooks.done.tap('SimplePlugin', (stats) => {
      console.log('构建完成,耗时:', stats.endTime - stats.startTime, 'ms');
    });
  }
}

module.exports = SimpleWebpackPlugin;

6. 开发环境优化

6.1 热更新配置

module.exports = {
  devServer: {
    static: {
      directory: path.join(__dirname, 'public'),
    },
    compress: true,
    port: 3000,
    hot: true,
    liveReload: true,
    historyApiFallback: true,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        pathRewrite: { '^/api': '' },
      },
    },
    client: {
      overlay: {
        errors: true,
        warnings: false,
      },
    },
  },
  
  // Source Map 配置
  devtool: 'eval-cheap-module-source-map',
  
  // 缓存配置
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename],
    },
  },
};

6.2 模块热替换(HMR)

// src/index.js
if (module.hot) {
  module.hot.accept('./app.js', function() {
    console.log('接受 app.js 模块的更新');
    // 执行更新逻辑
  });
  
  module.hot.dispose(function(data) {
    // 清理工作
  });
}

7. 生产环境构建优化

7.1 代码分割与优化

module.exports = {
  optimization: {
    // 代码分割
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10,
          reuseExistingChunk: true,
        },
        common: {
          name: 'common',
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true,
        },
      },
    },
    
    // 运行时 chunk
    runtimeChunk: {
      name: 'runtime',
    },
    
    // 模块 ID 优化
    moduleIds: 'deterministic',
    chunkIds: 'deterministic',
  },
};

7.2 Tree Shaking 配置

module.exports = {
  // 启用 Tree Shaking
  mode: 'production',
  
  optimization: {
    usedExports: true,
    sideEffects: false,
  },
  
  // package.json 中标记副作用
  // "sideEffects": [
  //   "*.css",
  //   "*.scss"
  // ]
};

8. 性能优化高级技巧

8.1 构建性能优化

module.exports = {
  // 解析优化
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      'components': path.resolve(__dirname, 'src/components'),
    },
    modules: [path.resolve(__dirname, 'node_modules')],
  },
  
  // 排除大型库
  externals: {
    react: 'React',
    'react-dom': 'ReactDOM',
    lodash: '_',
  },
  
  // 并行处理
  parallelism: 4,
  
  // 缓存
  cache: {
    type: 'filesystem',
    version: '1.0',
    buildDependencies: {
      config: [__filename],
    },
  },
};

8.2 运行时性能优化

// 预加载和预获取
import(/* webpackPreload: true */ 'ChartingLibrary');
import(/* webpackPrefetch: true */ 'LoginModal');

// 动态导入
const LazyComponent = lazy(() => import('./LazyComponent'));

9. 微前端与现代化架构

9.1 Module Federation 配置

// host-app/webpack.config.js
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

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

// remote-app/webpack.config.js
new ModuleFederationPlugin({
  name: 'app1',
  filename: 'remoteEntry.js',
  exposes: {
    './Button': './src/Button',
    './Widget': './src/Widget',
  },
  shared: {
    react: { singleton: true },
    'react-dom': { singleton: true },
  },
});

10. 自定义扩展与最佳实践

10.1 多环境配置管理

// webpack.common.js
const commonConfig = {
  // 通用配置
};

// webpack.dev.js
const { merge } = require('webpack-merge');
module.exports = merge(commonConfig, {
  mode: 'development',
  // 开发环境特定配置
});

// webpack.prod.js
module.exports = merge(commonConfig, {
  mode: 'production',
  // 生产环境特定配置
});

10.2 构建监控与分析

// 构建速度分析
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const smp = new SpeedMeasurePlugin();

module.exports = smp.wrap({
  // webpack 配置
});

// 打包体积分析
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin({
      analyzerMode: 'server',
      analyzerPort: 8888,
    }),
  ],
};

🎯 最佳实践总结

开发阶段

  1. 使用合适的 source map
  2. 启用 HMR 提高开发效率
  3. 配置合理的缓存策略
  4. 使用 webpack-dev-server

生产构建

  1. 代码分割和懒加载
  2. Tree Shaking 消除死代码
  3. 资源压缩和优化
  4. 长期缓存策略

性能优化

  1. 并行处理提升构建速度
  2. 合理使用 externals
  3. 模块联邦实现微前端
  4. 持续监控和分析

维护建议

  1. 配置文件模块化
  2. 版本控制和文档
  3. 团队规范统一
  4. 定期依赖更新

通过系统学习 Webpack 的配置和优化技巧,你将能够构建高效、可维护的前端应用架构,应对各种复杂的业务场景。这份指南涵盖了从基础到高级的完整知识体系,建议结合实际项目实践来深入掌握。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值