一、Webpack 在做什么
Webpack 是一个模块打包器:把项目里所有资源(JS、CSS、图片、字体)当作模块,通过 loader 处理、plugin 增强,最终打包成浏览器能直接加载的静态文件。
二、四大核心概念
entry:入口
1 2 3 4 5 6 7 8 9
| module.exports = { entry: './src/main.js', entry: { home: './src/home.js', admin: './src/admin.js' } }
|
output:出口
1 2 3 4 5 6 7 8
| module.exports = { output: { path: path.resolve(__dirname, 'dist'), filename: 'js/[name].[contenthash:8].js', clean: true } }
|
loader:处理非 JS 资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| module.exports = { module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: 'babel-loader' }, { test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] }, { test: /\.(png|jpg|jpeg|svg)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 8 * 1024 } } } ] } }
|
注意 use 数组是从右往左执行的(css-loader 先解析,style-loader 再注入)。
plugin:做 loader 做不到的事
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const HtmlWebpackPlugin = require('html-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = { plugins: [ new HtmlWebpackPlugin({ template: './public/index.html' }), new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash:8].css' }) ] }
|
三、开发模式与生产模式
用环境变量区分配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| const isProd = process.env.NODE_ENV === 'production'
module.exports = { mode: isProd ? 'production' : 'development', devtool: isProd ? 'source-map' : 'eval-cheap-module-source-map',
devServer: { port: 8080, hot: true, proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true } } },
optimization: { minimize: isProd } }
|
1 2 3 4 5 6 7
| { "scripts": { "dev": "webpack serve --mode development", "build": "NODE_ENV=production webpack --mode production" } }
|
四、代码分割:cacheGroups
公共依赖(react、lodash 等)单独拆 chunk,利用浏览器缓存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| module.exports = { optimization: { splitChunks: { cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all' }, common: { name: 'common', minChunks: 2, chunks: 'all' } } } } }
|
配合动态 import 的懒加载:
1 2
| const Admin = () => import('./pages/Admin')
|
五、持久化缓存:构建提速关键
Webpack 5 内置持久化缓存,二次构建时间大幅下降:
1 2 3 4 5 6 7 8
| module.exports = { cache: { type: 'filesystem', buildDependencies: { config: [__filename] } } }
|
配合 moduleIds: 'deterministic'(Webpack 5 默认),模块 id 稳定,改代码不会让所有 chunk 的 hash 全变。
六、性能分析
1
| npm install -D webpack-bundle-analyzer
|
1 2 3 4 5 6 7 8
| const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = { plugins: [ ...(process.env.ANALYZE ? [new BundleAnalyzerPlugin()] : []) ] }
|
1
| ANALYZE=true npm run build
|
看分析图定位体积大户:换用体积更小的库(dayjs 替代 moment)→ 按需引入 → 拆 chunk → 懒加载。
常见坑
- 图片路径 404:
publicPath 没配或配错,output.publicPath: '/' 是常见修复;
- HMR 不生效:确认
devServer.hot: true 且入口引用了热更新入口;
- 构建内存溢出:大项目
--max-old-space-size 调 Node 内存,或开启持久化缓存;
- contenthash 全变:检查是否用了
moduleIds: 'named'(开发默认),生产要用 deterministic。
总结
Webpack 5 的掌握路径:四大概念(entry/output/loader/plugin)→ 开发/生产双模式 → splitChunks 分包 + 懒加载 → 持久化缓存提速 → 分析插件瘦身。虽然新项目多用 Vite,但维护老项目、做深度构建定制时,Webpack 的知识仍然值钱。