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 中的@import和url(),并处理模块化(当开启 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 配置的扩展。理解这套“转译-加载-分割”机制,就能灵活定制自己的构建流程。