生产环境优化
生产环境优化是 Webpack 配置的重要部分。本章介绍代码压缩、Tree Shaking、作用域提升等生产环境优化技巧。
📋 学习目标
- ✅ 掌握代码压缩配置
- ✅ 理解 Tree Shaking 原理
- ✅ 学会作用域提升
- ✅ 掌握资源优化技巧
- ✅ 了解生产环境最佳实践
代码压缩
JavaScript 压缩
安装 TerserPlugin:
npm install --save-dev terser-webpack-plugin配置:
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
mode: 'production',
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // 移除 console
drop_debugger: true, // 移除 debugger
pure_funcs: ['console.log'] // 移除指定函数
},
format: {
comments: false // 移除注释
}
},
extractComments: false
})
]
}
}CSS 压缩
安装 CssMinimizerPlugin:
npm install --save-dev css-minimizer-webpack-plugin配置:
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{
discardComments: { removeAll: true }
}
]
}
})
]
}
}HTML 压缩
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
minifyJS: true,
minifyCSS: true
}
})
]
}Tree Shaking
Tree Shaking 用于移除未使用的代码。
启用 Tree Shaking
module.exports = {
mode: 'production', // 自动启用 Tree Shaking
optimization: {
usedExports: true,
sideEffects: false
}
}标记副作用
在 package.json 中标记副作用:
{
"sideEffects": false // 无副作用,可以安全地进行 Tree Shaking
}或者指定有副作用的文件:
{
"sideEffects": [
"*.css",
"*.scss",
"./src/polyfills.js"
]
}ES Module 要求
Tree Shaking 要求使用 ES Module:
// ✅ 支持 Tree Shaking
import { func1, func2 } from './utils'
export { func1 }
// ❌ 不支持 Tree Shaking
const utils = require('./utils')
module.exports = utils示例
utils.js:
export function used() {
return 'used'
}
export function unused() {
return 'unused'
}index.js:
import { used } from './utils'
console.log(used())结果:unused 函数会被移除。
作用域提升(Scope Hoisting)
作用域提升可以减少函数声明和闭包,提升代码执行效率。
启用作用域提升
module.exports = {
optimization: {
concatenateModules: true // 启用作用域提升
}
}效果对比
未启用:
// 每个模块都被包装在函数中
(function(module, exports, __webpack_require__) {
// 模块代码
})启用后:
// 模块代码直接合并,减少函数包装
// 更少的闭包,更快的执行速度资源优化
图片优化
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8KB 以下转 base64
}
},
generator: {
filename: 'images/[hash][ext]'
}
}
]
}
}字体优化
module.exports = {
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[hash][ext]'
}
}
]
}
}使用 CDN
module.exports = {
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'lodash': '_'
},
output: {
publicPath: 'https://cdn.example.com/'
}
}生产环境配置示例
完整配置
const path = require('path')
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')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash:8].js',
chunkFilename: 'js/[name].[contenthash:8].chunk.js',
clean: true
},
devtool: 'source-map',
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
}),
new CssMinimizerPlugin()
],
usedExports: true,
sideEffects: false,
concatenateModules: true
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
removeComments: true,
collapseWhitespace: true
}
}),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css'
})
]
}最佳实践
1. 使用 contenthash 实现长期缓存
module.exports = {
output: {
filename: '[name].[contenthash:8].js'
}
}2. 分离第三方库
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
}3. 使用 Source Map(可选)
module.exports = {
devtool: 'source-map' // 或 'hidden-source-map'
}4. 启用 Gzip 压缩
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
plugins: [
new CompressionPlugin({
algorithm: 'gzip'
})
]
}总结
- 代码压缩:使用 TerserPlugin 和 CssMinimizerPlugin
- Tree Shaking:移除未使用的代码
- 作用域提升:减少函数包装,提升性能
- 资源优化:图片、字体等资源优化
- 长期缓存:使用 contenthash 实现缓存优化