以下是一个详细的 Webpack 5 配置示例,包含常见资源处理和性能优化方案:
const path = require('path');
const webpack = require('webpack');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: isProduction
? 'js/[name].[contenthash:8].js'
: 'js/[name].js',
chunkFilename: isProduction
? 'js/[name].[contenthash:8].chunk.js'
: 'js/[name].chunk.js',
assetModuleFilename: 'assets/[hash][ext][query]',
clean: true,
},
mode: isProduction ? 'production' : 'development',
devtool: isProduction ? 'source-map' : 'eval-cheap-module-source-map',
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
modules: ['node_modules', path.resolve(__dirname, 'src')],
},
module: {
rules: [
// JavaScript/JSX 处理
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
}
}
},
// CSS 处理
{
test: /\.css$/,
use: [
isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
auto: true,
localIdentName: isProduction
? '[hash:base64]'
: '[path][name]__[local]',
},
},
},
'postcss-loader',
]
},
// 图片处理
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 10kb 以下转 base64
}
}
},
// 字体处理
{
test: /\.(woff2?|eot|ttf|otf)$/,
type: 'asset/resource',
},
]
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
minify: isProduction,
}),
isProduction && new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
chunkFilename: 'css/[name].[contenthash:8].chunk.css',
}),
new webpack.ProgressPlugin(),
new BundleAnalyzerPlugin({
analyzerMode: 'disabled', // 不自动打开
generateStatsFile: true, // 生成 stats.json
}),
].filter(Boolean),
optimization: {
minimize: isProduction,
minimizer: [
new TerserPlugin({
parallel: true,
extractComments: false,
terserOptions: {
compress: {
drop_console: true,
}
}
}),
new CssMinimizerPlugin(),
],
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
common: {
minChunks: 2,
name: 'common',
chunks: 'all',
priority: 10,
reuseExistingChunk: true,
}
}
},
runtimeChunk: {
name: entrypoint => `runtime-${entrypoint.name}`,
},
},
performance: {
maxEntrypointSize: 512 * 1024, // 512kb
maxAssetSize: 512 * 1024,
hints: isProduction ? 'warning' : false,
},
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 3000,
hot: true,
historyApiFallback: true,
client: {
overlay: {
errors: true,
warnings: false,
},
},
},
};
};
主要优化配置解析:
代码分割 (Code Splitting)
- 通过
splitChunks
配置自动拆分第三方库(vendor)和公共代码 - 单独提取 runtime 代码
- 动态导入实现按需加载
- 通过
缓存策略
- 输出文件名使用
[contenthash]
- 使用
babel-loader
的cacheDirectory
- 使用
HardSourceWebpackPlugin
(需单独安装)
- 输出文件名使用
资源优化
- 图片小于 10KB 转为 base64
- 自动压缩 CSS 和 JS
- 移除 console 语句
- Tree Shaking (生产模式自动启用)
构建性能优化
- 使用
thread-loader
并行处理(需单独添加) - 缩小 loader 作用范围(exclude: /node_modules/)
- 使用更快的
swc-loader
替代 babel(实验性)
- 使用
开发体验优化
- 热模块替换(HMR)
- 更快的 source-map 策略
- 进度显示
分析工具
- 生成构建分析报告(stats.json)
- 使用
webpack-bundle-analyzer
扩展优化建议:
PWA 支持
const WorkboxPlugin = require('workbox-webpack-plugin'); // 添加 plugins new WorkboxPlugin.GenerateSW({ clientsClaim: true, skipWaiting: true, })
预加载关键资源
new HtmlWebpackPlugin({ // ... preload: 'initial', prefetch: ['asyncChunk'], })
CDN 加速
output: { publicPath: 'https://cdn.example.com/', }
DLL 加速构建
new webpack.DllReferencePlugin({ manifest: require('./dll/vendor-manifest.json') })
多线程处理
{ test: /\.js$/, use: [ 'thread-loader', 'babel-loader' ] }
根据项目实际需求选择优化策略,建议通过以下命令分析构建结果:
npx webpack --profile --json > stats.json
然后使用 Webpack Analyse 或 webpack-bundle-analyzer
分析打包结果。