Webpack 5 项目基本配置详解
一、Webpack 核心概念
1.1 Webpack 是什么?
Webpack 是一个静态模块打包器,它将所有资源(JS、CSS、图片等)视为模块,通过依赖关系构建依赖图,最终打包成浏览器可识别的静态资源。
1.2 五个核心概念
- Entry(入口):构建依赖图的起点
- Output(输出):打包后的资源输出位置
- Loader(加载器):处理非JS文件,将其转换为模块
- Plugin(插件):扩展功能,优化打包结果
- Mode(模式):开发模式或生产模式
二、基础项目配置
2.1 项目初始化
# 创建项目目录
mkdir webpack5-demo
cd webpack5-demo
# 初始化package.json
npm init -y
# 安装Webpack
npm install webpack webpack-cli --save-dev
2.2 目录结构
webpack5-demo/
├── src/
│ ├── index.js # 入口文件
│ ├── styles/
│ │ └── main.css
│ └── assets/
│ └── images/
├── public/
│ └── index.html
├── dist/ # 打包输出目录
├── webpack.config.js # Webpack配置文件
└── package.json
三、基础配置文件详解
3.1 基础配置(webpack.config.js)
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 1. 入口配置
entry: {
main: './src/index.js',
vendor: './src/vendor.js' // 多入口示例
},
// 2. 输出配置
output: {
// 输出目录(绝对路径)
path: path.resolve(__dirname, 'dist'),
// 输出文件名,[name]对应入口的key,[contenthash]根据内容生成hash
filename: '[name].[contenthash].bundle.js',
// 清理dist目录
clean: true,
// 静态资源输出路径
assetModuleFilename: 'assets/[hash][ext][query]'
},
// 3. 模式配置
mode: 'development', // 'production' | 'development' | 'none'
// 4. 开发服务器配置
devServer: {
static: {
directory: path.join(__dirname, 'dist'),
},
// 热更新
hot: true,
// 开启gzip压缩
compress: true,
port: 8080,
open: true,
// 代理配置
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '' },
changeOrigin: true
}
}
},
// 5. 模块配置(Loader配置)
module: {
rules: [
// CSS处理
{
test: /\.css$/i,
use: [
'style-loader', // 将CSS插入到DOM
'css-loader' // 解析CSS文件
],
},
// SCSS/SASS处理
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
'sass-loader'
],
},
// 图片资源处理
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[hash][ext][query]'
}
},
// 字体文件处理
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
// Babel配置(JS/JSX转译)
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react'
],
plugins: [
'@babel/plugin-transform-runtime'
]
}
}
},
// TypeScript处理
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
}
],
},
// 6. 插件配置
plugins: [
// 生成HTML文件
new HtmlWebpackPlugin({
title: 'Webpack5 Demo',
template: './public/index.html',
filename: 'index.html',
// 压缩HTML
minify: {
collapseWhitespace: true,
removeComments: true,
removeRedundantAttributes: true,
useShortDoctype: true
}
}),
// 复制静态文件(示例)
// new CopyWebpackPlugin({
// patterns: [
// { from: 'public/favicon.ico', to: 'favicon.ico' }
// ]
// })
],
// 7. 解析配置
resolve: {
// 自动解析扩展名
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
// 路径别名
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
}
},
// 8. 优化配置
optimization: {
// 代码分割
splitChunks: {
chunks: 'all',
cacheGroups: {
// 第三方模块
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
// 公共模块
common: {
minChunks: 2,
name: 'common',
chunks: 'all',
priority: -10
}
}
},
// 最小化
minimizer: [
// 生产环境自动添加TerserPlugin(压缩JS)
`...`, // 继承默认的minimizer
],
},
// 9. 性能提示
performance: {
hints: 'warning', // 'error' | 'warning' | false
maxAssetSize: 200000, // 200kb
maxEntrypointSize: 400000, // 400kb
}
};
四、开发环境与生产环境分离配置
4.1 配置文件拆分
创建三个配置文件:
webpack.common.js - 公共配置
webpack.dev.js - 开发环境配置
webpack.prod.js - 生产环境配置
4.2 公共配置文件(webpack.common.js)
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js',
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
resolve: {
extensions: ['.js', '.jsx'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
};
4.3 开发环境配置(webpack.dev.js)
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map', // 源码映射
devServer: {
static: './dist',
hot: true,
port: 8080,
open: true,
historyApiFallback: true, // 支持SPA路由
},
optimization: {
minimize: false, // 开发环境不压缩
},
// 开发环境性能提示关闭
performance: {
hints: false,
},
});
4.4 生产环境配置(webpack.prod.js)
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map', // 生产环境源码映射
module: {
rules: [
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader, // 提取CSS为单独文件
'css-loader',
],
},
],
},
plugins: [
// 提取CSS到单独文件
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css',
}),
],
optimization: {
minimizer: [
new TerserPlugin(), // 压缩JS
new CssMinimizerPlugin(), // 压缩CSS
],
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
runtimeChunk: 'single', // 运行时代码单独打包
},
performance: {
hints: 'warning',
maxEntrypointSize: 512000,
maxAssetSize: 512000,
},
});
4.5 package.json脚本配置
{
"scripts": {
"start": "webpack serve --config webpack.dev.js",
"build": "webpack --config webpack.prod.js",
"build:analyze": "webpack --config webpack.prod.js --profile --json > stats.json",
"dev": "webpack serve --config webpack.dev.js",
"test": "echo \"Error: no test specified\" && exit 1"
}
}
五、常用Loader和插件详解
5.1 常用Loader
| Loader |
作用 |
安装命令 |
|---|
| babel-loader |
转译ES6+代码 |
npm install -D babel-loader @babel/core @babel/preset-env |
| css-loader |
解析CSS文件 |
npm install -D css-loader |
| style-loader |
将CSS注入DOM |
npm install -D style-loader |
| sass-loader |
编译Sass/SCSS |
npm install -D sass-loader sass |
| less-loader |
编译Less |
npm install -D less-loader less |
| postcss-loader |
处理CSS兼容性 |
npm install -D postcss-loader postcss autoprefixer |
| file-loader |
处理文件资源 |
npm install -D file-loader |
| url-loader |
小文件转base64 |
npm install -D url-loader |
| ts-loader |
编译TypeScript |
npm install -D ts-loader typescript |
5.2 常用插件
| 插件 |
作用 |
安装命令 |
|---|
| HtmlWebpackPlugin |
生成HTML文件 |
npm install -D html-webpack-plugin |
| MiniCssExtractPlugin |
提取CSS为单独文件 |
npm install -D mini-css-extract-plugin |
| CleanWebpackPlugin |
清理输出目录 |
npm install -D clean-webpack-plugin |
| CopyWebpackPlugin |
复制静态文件 |
npm install -D copy-webpack-plugin |
| DefinePlugin |
定义环境变量 |
Webpack内置 |
| ProvidePlugin |
自动加载模块 |
Webpack内置 |
| BundleAnalyzerPlugin |
分析包大小 |
npm install -D webpack-bundle-analyzer |
六、高级配置技巧
6.1 环境变量配置
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.API_URL': JSON.stringify(process.env.API_URL),
}),
],
};
6.2 缓存配置
module.exports = {
cache: {
type: 'filesystem', // 使用文件系统缓存
cacheDirectory: path.resolve(__dirname, '.temp_cache'),
buildDependencies: {
config: [__filename], // 当配置文件改变时,使缓存失效
},
},
output: {
filename: '[name].[contenthash].js', // 内容hash
},
};
6.3 排除外部依赖
module.exports = {
externals: {
react: 'React',
'react-dom': 'ReactDOM',
lodash: '_',
jquery: 'jQuery',
},
};
七、最佳实践建议
7.1 性能优化
使用多线程/多进程构建
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: true, // 开启多线程
}),
],
},
};
合理配置splitChunks
optimization: {
splitChunks: {
chunks: 'all',
minSize: 20000, // 最小20kb
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
automaticNameDelimiter: '~',
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
}
7.2 开发体验优化
配置source map
// 开发环境
devtool: 'cheap-module-source-map',
// 生产环境
devtool: 'source-map',
配置热更新
devServer: {
hot: true,
liveReload: false,
},
八、完整示例配置
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: isProduction
? '[name].[contenthash].js'
: '[name].bundle.js',
chunkFilename: isProduction
? '[name].[contenthash].chunk.js'
: '[name].chunk.js',
},
mode: isProduction ? 'production' : 'development',
devtool: isProduction ? 'source-map' : 'eval-source-map',
devServer: {
static: './dist',
hot: true,
port: 3000,
open: true,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.css$/,
use: [
isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'postcss-loader',
],
},
{
test: /\.(png|jpg|gif|svg)$/,
type: 'asset/resource',
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
}),
...(isProduction
? [new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
})]
: []
),
],
optimization: {
splitChunks: {
chunks: 'all',
},
},
};
};
总结
Webpack 5 的配置虽然复杂,但理解其核心概念和配置项后,可以根据项目需求灵活配置。建议:
从简单配置开始,逐步添加功能
分离开发和生产环境,使用webpack-merge
合理使用缓存,提升构建速度
定期分析打包结果,优化打包体积
保持Webpack和相关依赖更新
通过合理配置Webpack,可以显著提升开发效率和项目性能。