人人都会AI编程

17.2 Webpack 构建 React 项目

更新时间:2026-07-10

Webpack 是 React 项目经典的打包工具,配合 Babel 处理 JSX 与 ES6+ 语法,通过 Loader 加载各类资源,并利用代码分割优化加载性能。下面重点介绍 Babel 配置、Loader 配置和代码分割三个核心部分。

Babel 配置:转译 JSX 与现代 JavaScript

Babel 负责将 JSX 和 ES6+ 代码转换为浏览器能识别的 ES5 或更低版本。在 React 项目中,需要配置以下预设和插件:

安装依赖

npm install -D babel-loader @babel/core @babel/preset-env @babel/preset-react
# 如果使用 TypeScript,还需
npm install -D @babel/preset-typescript

基础配置(babel.config.js 或 .babelrc)

module.exports = {
  presets: [
    ['@babel/preset-env', {
      // 根据目标浏览器自动决定转换哪些语法
      targets: '> 0.25%, not dead',
      // 按需引入 core-js 的 polyfill
      useBuiltIns: 'usage',
      corejs: 3
    }],
    ['@babel/preset-react', {
      // React 17+ 可使用自动 JSX 转换,无需手动引入 React
      runtime: 'automatic'
    }]
  ]
};

关键点解释

  • @babel/preset-env 智能转换 ES6+ 语法,useBuiltIns: 'usage' 根据代码中实际使用的特性按需注入 polyfill,避免全量引入 core-js。
  • @babel/preset-react 处理 JSX 转换。runtime: 'automatic' 启用 React 17 引入的新 JSX 转换,无需在每个文件顶部写 import React from 'react',同时打包体积略有优化。
  • 若项目使用 TypeScript,添加 @babel/preset-typescript(或直接使用 ts-loader / swc-loader,但 Babel 方案更常见)。

Loader 配置:处理 CSS、图片等资源

Webpack 只能理解 JavaScript,所有非 JS 资源都需要通过对应的 Loader 转换为模块。

CSS 处理

npm install -D css-loader style-loader
# 若使用 CSS Modules 或预处理器(Sass)
npm install -D sass-loader sass

配置示例(webpack.config.js module.rules 部分):

module: {
  rules: [
    {
      test: /\.css$/,
      use: ['style-loader', 'css-loader']
    },
    {
      test: /\.module\.css$/,  // CSS Modules 文件命名约定 *.module.css
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            modules: {
              localIdentName: '[name]__[local]--[hash:base64:5]'
            }
          }
        }
      ]
    },
    {
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader']
    }
  ]
}
  • style-loader 将 CSS 通过 <style> 标签注入 DOM,适合开发环境;生产环境通常用 MiniCssExtractPlugin.loader 抽离成独立文件。
  • css-loader 解析 CSS 中的 @importurl(),并处理模块化(当开启 modules 选项时)。
  • CSS Modules 自动生成局部作用域类名,避免全局样式污染。

图片与静态资源处理
Webpack 5 内置资源模块,无需额外 loader:

rules: [
  {
    test: /\.(png|jpe?g|gif|svg)$/i,
    type: 'asset',
    parser: {
      dataUrlCondition: {
        maxSize: 8 * 1024 // 8KB 以下转 base64 内联
      }
    }
  },
  {
    test: /\.(woff|woff2|eot|ttf|otf)$/,
    type: 'asset/resource' // 始终输出为文件
  }
]

代码分割:优化加载性能

代码分割(Code Splitting)将应用拆分成多个 chunk,按需加载,减少首屏资源体积。React 项目中常见三类分割方式:

1. 动态 import() 实现组件懒加载

// 路由级懒加载
const LazyPage = lazy(() => import('./pages/LazyPage'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/lazy" element={<LazyPage />} />
      </Routes>
    </Suspense>
  );
}

Webpack 遇到动态 import() 语法时,会自动将目标模块拆分为独立 chunk,在页面需要时异步加载。React.lazy 与 Suspense 配合实现加载状态处理。

2. 手动配置 entry 多入口
适用于多页应用场景,每个页面独立入口,共享的公共模块可进一步提取。

3. SplitChunksPlugin 提取公共依赖
Webpack 内置的 SplitChunksPlugin 可自动提取公共的第三方库(如 react、react-dom)或业务公共模块,避免重复打包:

optimization: {
  splitChunks: {
    chunks: 'all',          // 对同步和异步 chunk 都生效
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        chunks: 'all'
      },
      common: {
        minChunks: 2,       // 被至少两个 chunk 引用时提取
        name: 'common',
        chunks: 'all',
        priority: -20
      }
    }
  }
}
  • vendor 分组将 node_modules 下的依赖单独打包成长久缓存的 vendors.[hash].js
  • common 分组提取业务模块中复用次数较高的公共代码。

配置效果: 构建后浏览器先加载必须的首屏 chunk(体积较小),当用户访问其他路由或交互触发时再异步加载对应 chunk,显著提升首次内容绘制速度。

以上是 Webpack 构建 React 项目最核心的三个配置维度。实际工程中通常还会集成 html-webpack-plugin 生成 HTML、eslint-webpack-plugin 进行语法检查等,但这些均可看作对基础 Loader/Babel 配置的扩展。理解这套“转译-加载-分割”机制,就能灵活定制自己的构建流程。