Appearance
Webpack 生产环境配置
生产环境配置专注于代码优化、性能提升和资源压缩,确保应用程序在生产环境中具有最佳性能。
生产环境基础配置
基础生产配置
javascript
module.exports = {
mode: 'production', // 生产模式
devtool: 'source-map', // 生产环境使用源映射便于调试
entry: './src/index.js',
output: {
filename: '[name].[contenthash].js', // 使用内容哈希实现长期缓存
chunkFilename: '[name].[contenthash].chunk.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/', // 或者使用 CDN 路径
clean: true // 构建前清理输出目录
}
};
优化配置
javascript
module.exports = {
mode: 'production',
optimization: {
minimize: true, // 启用代码压缩
minimizer: [
// JavaScript 压缩
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // 删除 console
drop_debugger: true, // 删除 debugger
pure_funcs: ['console.log'] // 删除特定函数调用
},
mangle: true, // 变量名混淆
format: {
comments: false // 删除注释
}
},
extractComments: false
})
],
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
chunks: 'all'
},
common: {
name: 'common',
minChunks: 2,
priority: 5,
chunks: 'all',
enforce: true
}
}
},
runtimeChunk: {
name: 'runtime'
}
}
};
代码压缩与优化
JavaScript 压缩
javascript
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: true, // 并行压缩
extractComments: 'all', // 提取注释到单独文件
terserOptions: {
compress: {
// 压缩选项
drop_console: true, // 删除 console 语句
drop_debugger: true, // 删除 debugger 语句
pure_funcs: [ // 删除纯函数调用
'console.debug',
'console.info'
],
passes: 2, // 压缩次数
reduce_funcs: false // 不减少函数
},
mangle: {
reserved: ['$', 'jQuery'] // 保留特定名称不被混淆
},
format: {
comments: false // 删除所有注释
}
}
})
]
}
};
CSS 压缩
javascript
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin({
test: /\.css$/g,
parallel: true, // 并行处理
minimizerOptions: {
preset: [
'default',
{
discardComments: { removeAll: true },
normalizeWhitespace: true
}
]
}
})
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css'
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // 提取 CSS 而不是注入到 JS 中
'css-loader'
]
}
]
}
};
资源优化
图片优化
javascript
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: 'asset', // Webpack 5 资源模块
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb 以下转为 base64
}
},
generator: {
filename: 'images/[name].[contenthash:8][ext]'
}
},
// 或者使用 imagemin 进行图片压缩
{
test: /\.(jpe?g|png|gif)$/i,
use: [
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
optipng: {
enabled: false
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false
}
}
}
]
}
]
}
};
字体优化
javascript
module.exports = {
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[contenthash:8][ext]'
}
}
]
}
};
代码分割策略
高级代码分割
javascript
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
maxInitialRequests: 10, // 最大初始化请求数
maxAsyncRequests: 10, // 最大异步请求数
cacheGroups: {
// 第三方库
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
chunks: 'initial',
maxSize: 244000 // 最大 244kb
},
// React 生态
react: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'react',
priority: 20,
chunks: 'initial'
},
// 公共代码
common: {
name: 'common',
minChunks: 2, // 至少被 2 个 chunk 使用
priority: 5,
chunks: 'initial',
minSize: 0 // 最小大小为 0
},
// 样式文件
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true // 强制创建 chunk
}
}
}
}
};
动态导入优化
javascript
// 在应用代码中使用动态导入
// src/App.js
const Home = lazy(() => import('./components/Home'));
const About = lazy(() => import('./components/About'));
// Webpack 配置
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
// 动态导入的代码
async: {
chunks: 'async',
minChunks: 1,
name(module) {
// 为动态导入创建有意义的名称
const path = require('path');
const fileName = module
.identifier()
.split('node_modules')[1]
.replace(/^[/\\]+/, '')
.replace(/[/\\]+/g, '-')
.split('.')[0];
return `async-${fileName}`;
}
}
}
}
}
};
缓存策略
长期缓存配置
javascript
module.exports = {
optimization: {
moduleIds: 'deterministic', // 确定性模块 ID
chunkIds: 'deterministic', // 确定性 chunk ID
runtimeChunk: 'single', // 单独的运行时 chunk
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
},
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
}
};
服务端缓存配置
javascript
// 结合服务器配置实现缓存
module.exports = {
output: {
filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].chunk.js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'https://cdn.example.com/assets/' // CDN 路径
},
plugins: [
// 生成资源映射文件
new WebpackManifestPlugin(),
// 生成子资源完整性 (SRI)
new SriPlugin({
hashFuncNames: ['sha256', 'sha384']
})
]
};
生产环境安全配置
安全优化
javascript
module.exports = {
optimization: {
sideEffects: false, // 正确标记副作用
providedExports: true, // 提供导出信息
usedExports: true, // 标记使用的导出(Tree Shaking)
concatenateModules: true // 模块串联(Scope Hoisting)
},
stats: {
all: false,
modules: false, // 不显示模块信息
maxModules: 0,
errors: true,
warnings: true
}
};
环境变量安全
javascript
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV ': JSON.stringify('production'),
'process.env.API_URL ': JSON.stringify(process.env.PROD_API_URL),
// 不要在生产环境中暴露敏感信息
'__DEV__': JSON.stringify(false),
'__PROD__': JSON.stringify(true)
})
]
};
性能监控与分析
Bundle 分析
javascript
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
// 生产环境分析(可选)
process.env.ANALYZE && new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: 'bundle-report.html'
})
].filter(Boolean) // 过滤掉 undefined
};
性能预算
javascript
module.exports = {
performance: {
maxAssetSize: 250000, // 单个资源最大 250kb
maxEntrypointSize: 250000, // 入口点最大 250kb
hints: 'warning' // 性能警告
}
};
生产环境完整配置示例
javascript
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'production',
devtool: 'source-map', // 生产环境源映射
entry: {
app: './src/index.js'
},
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
clean: true
},
optimization: {
minimize: true,
minimizer: [
// JavaScript 压缩
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
},
format: {
comments: false
}
},
extractComments: false
}),
// CSS 压缩
new CssMinimizerPlugin()
],
// 代码分割
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
chunks: 'all'
}
}
},
// 运行时代码分离
runtimeChunk: 'single',
// 模块 ID 优化
moduleIds: 'deterministic',
chunkIds: 'deterministic'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3
}]
]
}
}
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024
}
},
generator: {
filename: 'images/[name].[contenthash:8][ext]'
}
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
}
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css'
})
],
performance: {
maxAssetSize: 250000,
maxEntrypointSize: 250000,
hints: 'warning'
}
};
小结
生产环境配置的重点在于优化性能、减少文件大小和提高加载速度。关键配置包括代码压缩、资源优化、缓存策略、代码分割等。合理的生产环境配置能够显著提升用户体验和应用性能。