基础配置详解
深入学习 Webpack 的基础配置选项,包括 Entry、Output、Resolve 等配置的详细说明和最佳实践。
📋 学习目标
- ✅ 理解完整的配置结构
- ✅ 掌握 Entry 的各种配置方式
- ✅ 掌握 Output 的详细配置
- ✅ 理解 Resolve 配置(路径解析)
- ✅ 学会环境变量配置
完整配置结构
基础配置模板
const path = require('path')
module.exports = {
// 入口配置
entry: './src/index.js',
// 输出配置
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
// 模式
mode: 'development',
// 模块处理
module: {
rules: []
},
// 插件
plugins: [],
// 解析配置
resolve: {
extensions: ['.js', '.json'],
alias: {}
},
// 开发服务器
devServer: {},
// 优化配置
optimization: {}
}Entry 配置详解
1. 单入口(字符串)
module.exports = {
entry: './src/index.js'
}适用场景:单页面应用(SPA)
2. 多入口(对象)
module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js',
admin: './src/admin.js'
}
}适用场景:
- 需要分离第三方库代码
- 多页面应用
- 需要独立的入口点
3. 动态入口(函数)
module.exports = {
entry: () => {
return './src/index.js'
}
}高级用法:根据条件动态决定入口
module.exports = {
entry: () => {
return new Promise((resolve) => {
// 动态决定入口
const entry = process.env.NODE_ENV === 'production'
? './src/index.prod.js'
: './src/index.dev.js'
resolve(entry)
})
}
}4. 数组入口
module.exports = {
entry: ['./src/index.js', './src/polyfills.js']
}说明:多个文件会打包到一个 chunk 中
Output 配置详解
基础配置
const path = require('path')
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}完整配置选项
const path = require('path')
module.exports = {
output: {
// 输出目录(必须是绝对路径)
path: path.resolve(__dirname, 'dist'),
// 输出文件名(单入口)
filename: 'bundle.js',
// 输出文件名(多入口,使用占位符)
filename: '[name].bundle.js',
// 非入口 chunk 的文件名
chunkFilename: '[name].chunk.js',
// 公共路径(CDN 路径)
publicPath: '/',
// 清理输出目录
clean: true,
// 资源模块的文件名
assetModuleFilename: 'assets/[hash][ext]',
// 输出库的配置(用于库开发)
library: {
name: 'MyLibrary',
type: 'umd'
}
}
}文件名占位符
module.exports = {
output: {
filename: '[name].[contenthash:8].js'
}
}可用占位符:
[name]- chunk 名称[id]- chunk ID[hash]- 整个项目的 hash[chunkhash]- chunk 的 hash[contenthash]- 内容的 hash(推荐)[fullhash]- 完整 hash
Hash 长度:[contenthash:8] 表示只取前 8 位
多入口输出配置
module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash].js',
chunkFilename: 'js/[name].[contenthash].chunk.js'
}
}输出结果:
dist/js/main.abc123.jsdist/js/vendor.def456.js
Resolve 配置(路径解析)
Resolve 配置告诉 Webpack 如何解析模块路径。
基础配置
module.exports = {
resolve: {
// 自动解析的扩展名
extensions: ['.js', '.json', '.jsx', '.ts', '.tsx'],
// 路径别名
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
},
// 模块查找目录
modules: [
path.resolve(__dirname, 'src'),
'node_modules'
]
}
}extensions 配置
module.exports = {
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
}
}说明:配置后可以省略文件扩展名
// 可以这样导入
import App from './App' // 自动查找 App.js, App.jsx, App.ts, App.tsxalias 配置(路径别名)
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils'),
'@assets': path.resolve(__dirname, 'src/assets')
}
}
}使用示例:
// 使用别名
import Button from '@components/Button'
import { formatDate } from '@utils/date'
import logo from '@assets/logo.png'
// 而不是
import Button from '../../../components/Button'modules 配置
module.exports = {
resolve: {
modules: [
path.resolve(__dirname, 'src'), // 优先查找 src 目录
'node_modules' // 然后查找 node_modules
]
}
}说明:配置后可以直接从 src 目录导入
// 可以直接这样导入
import utils from 'utils' // 自动从 src/utils 查找完整 Resolve 配置示例
const path = require('path')
module.exports = {
resolve: {
extensions: ['.tsx', '.ts', '.js', '.jsx', '.json'],
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils'),
'@styles': path.resolve(__dirname, 'src/styles'),
'@assets': path.resolve(__dirname, 'src/assets')
},
modules: [
path.resolve(__dirname, 'src'),
'node_modules'
],
// 解析包的主入口
mainFields: ['browser', 'module', 'main'],
// 解析包的主文件
mainFiles: ['index']
}
}环境变量配置
使用 DefinePlugin
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.API_URL': JSON.stringify('https://api.example.com')
})
]
}使用 dotenv
npm install --save-dev dotenv-webpack创建 .env 文件:
# .env
NODE_ENV=development
API_URL=http://localhost:8080配置 webpack:
const Dotenv = require('dotenv-webpack')
module.exports = {
plugins: [
new Dotenv({
path: '.env', // 默认是 .env
safe: false, // 如果 .env.example 存在,使用它作为模板
systemvars: true // 加载系统变量
})
]
}多环境配置
创建不同环境的 .env 文件:
.env.development.env.production.env.test
webpack.config.js:
const Dotenv = require('dotenv-webpack')
const path = require('path')
module.exports = (env) => {
const envFile = `.env.${env.NODE_ENV || 'development'}`
return {
plugins: [
new Dotenv({
path: path.resolve(__dirname, envFile)
})
]
}
}其他重要配置
Context 配置
module.exports = {
context: path.resolve(__dirname, 'src'),
entry: './index.js' // 相对于 context
}Target 配置
module.exports = {
target: 'web', // 默认值,用于浏览器
// target: 'node', // 用于 Node.js
// target: 'electron-main', // 用于 Electron 主进程
}Externals 配置
module.exports = {
externals: {
jquery: 'jQuery', // 从 CDN 引入,不打包
react: 'React',
'react-dom': 'ReactDOM'
}
}配置最佳实践
1. 使用函数式配置
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production'
return {
mode: isProduction ? 'production' : 'development',
output: {
filename: isProduction
? '[name].[contenthash].js'
: '[name].js'
}
}
}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].js'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
}webpack.dev.js:
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map'
})webpack.prod.js:
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map'
})3. 使用环境变量
module.exports = (env) => {
return {
output: {
publicPath: env.production
? 'https://cdn.example.com/'
: '/'
}
}
}完整配置示例
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
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',
publicPath: '/',
clean: true
},
mode: isProduction ? 'production' : 'development',
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'@': path.resolve(__dirname, 'src')
},
modules: [
path.resolve(__dirname, 'src'),
'node_modules'
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(argv.mode)
})
]
}
}总结
- Entry:支持字符串、对象、函数等多种配置方式
- Output:使用占位符实现灵活的文件命名
- Resolve:配置路径别名和扩展名,简化导入
- 环境变量:使用 DefinePlugin 或 dotenv 管理环境变量
- 最佳实践:分离配置、使用函数式配置