Appearance
Webpack 开发环境配置
开发环境配置是 Webpack 设置的重要组成部分,它直接影响开发体验、构建速度和调试效率。本章将详细介绍如何配置适合开发环境的 Webpack。
开发环境基础配置
基础开发配置
javascript
module.exports = {
mode: 'development', // 开发模式
devtool: 'eval-source-map', // 生成源映射,便于调试
entry: './src/index.js', // 入口文件
output: {
filename: '[name].js', // 不使用哈希,便于调试
path: path.resolve(__dirname, 'dist'),
publicPath: '/' // 开发服务器公共路径
}
};
开发服务器配置
javascript
module.exports = {
mode: 'development',
entry: './src/index.js',
devServer: {
static: { // 静态文件服务
directory: path.join(__dirname, 'public'),
watch: true // 监听文件变化
},
compress: true, // 启用 gzip 压缩
port: 3000, // 端口号
open: true, // 自动打开浏览器
hot: true, // 启用热模块替换
historyApiFallback: true, // 支持 HTML5 History API
client: {
overlay: true, // 显示编译错误
progress: true // 显示编译进度
}
}
};
源映射配置
开发环境源映射选项
javascript
module.exports = {
mode: 'development',
devtool: 'eval-source-map', // 最佳调试体验,但构建较慢
// devtool: 'eval', // 构建最快,但调试体验一般
// devtool: 'eval-cheap-source-map', // 平衡构建速度和调试体验
// devtool: 'eval-cheap-module-source-map', // 推荐用于开发
entry: './src/index.js'
};
// 不同 devtool 选项的对比:
// 'eval' - 构建最快,但无法显示原始代码
// 'eval-source-map' - 调试最佳,但构建最慢
// 'eval-cheap-module-source-map' - 推荐开发使用
// 'eval-cheap-source-map' - 较快的构建和较好的调试
生产环境源映射配置
javascript
module.exports = {
mode: 'production',
devtool: 'source-map', // 生产环境使用完整源映射
// devtool: 'hidden-source-map', // 不在浏览器中显示源映射
// devtool: 'nosources-source-map', // 不包含源代码
entry: './src/index.js'
};
热模块替换(HMR)
基础 HMR 配置
javascript
const webpack = require('webpack');
module.exports = {
mode: 'development',
entry: './src/index.js',
devServer: {
hot: true // 启用热模块替换
},
plugins: [
new webpack.HotModuleReplacementPlugin() // HMR 插件
]
};
React HMR 配置
javascript
module.exports = {
mode: 'development',
entry: './src/index.js',
devServer: {
hot: true
},
module: {
rules: [
{
test: /\.jsx?$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react'],
plugins: [
'react-refresh/babel' // React Fast Refresh
]
}
},
exclude: /node_modules/
}
]
},
plugins: [
new ReactRefreshWebpackPlugin() // React Fast Refresh 插件
]
};
Vue HMR 配置
javascript
module.exports = {
mode: 'development',
entry: './src/main.js',
devServer: {
hot: true
},
module: {
rules: [
{
test: /\.vue$/,
use: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin()
]
};
开发服务器高级配置
代理配置
javascript
module.exports = {
mode: 'development',
devServer: {
static: './dist',
port: 3000,
proxy: { // 代理配置
'/api': {
target: 'http://localhost:8080', // 目标服务器
changeOrigin: true, // 改变源
secure: false, // 不验证 SSL 证书
pathRewrite: { // 路径重写
'^/api': '/api/v1'
},
onProxyReq: (proxyReq, req, res) => {
// 代理请求时的回调
console.log('Proxying request:', req.url);
}
},
// 多个代理配置
'/auth': {
target: 'http://auth-server:3001',
changeOrigin: true
}
}
}
};
HTTPS 配置
javascript
module.exports = {
devServer: {
static: './dist',
https: true, // 启用 HTTPS
// 或者自定义证书
https: {
key: fs.readFileSync('/path/to/server.key'),
cert: fs.readFileSync('/path/to/server.crt'),
ca: fs.readFileSync('/path/to/ca.pem')
},
port: 3000
}
};
多页面应用配置
javascript
module.exports = {
mode: 'development',
entry: {
home: './src/pages/home/index.js',
about: './src/pages/about/index.js',
contact: './src/pages/contact/index.js'
},
devServer: {
static: {
directory: path.join(__dirname, 'public')
},
port: 3000,
historyApiFallback: {
// 多页面应用的路由回退
rewrites: [
{ from: /^\/$/, to: '/home.html' },
{ from: /^\/home/, to: '/home.html' },
{ from: /^\/about/, to: '/about.html' },
{ from: /^\/contact/, to: '/contact.html' }
]
}
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
}
};
## 性能优化配置
### 开发环境性能优化
```javascript
module.exports = {
mode: 'development',
// 启用缓存以加快重建速度
cache: {
type: 'filesystem', // 文件系统缓存
buildDependencies: {
config: [__filename] // 配置文件变更时清除缓存
}
},
// 优化构建性能
optimization: {
moduleIds: 'named', // 使用命名模块 ID,便于调试
chunkIds: 'named', // 使用命名块 ID
emitOnErrors: false, // 构建错误时不输出资源
splitChunks: {
chunks: 'all',
cacheGroups: {
// 开发环境可能不需要复杂的代码分割
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
chunks: 'all'
}
}
}
},
// 减少监听文件的数量
snapshot: {
managedPaths: [ // Webpack 监控的路径
path.resolve(__dirname, 'node_modules')
],
immutablePaths: [ // 不变路径
path.resolve(__dirname, 'immutable-deps')
]
}
};
模块解析优化
javascript
module.exports = {
resolve: {
// 优化模块解析
modules: [
path.resolve(__dirname, 'src'), // 优先查找项目源码
'node_modules' // 然后查找 node_modules
],
// 减少扩展名尝试
extensions: ['.js', '.jsx', '.ts', '.tsx'],
// 使用别名减少解析时间
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
},
// 解析时的主字段
mainFields: ['browser', 'module', 'main']
},
// 排除不需要解析的模块
module: {
noParse: [
/jquery/, // 不解析 jQuery
/lodash/ // 不解析 Lodash
]
}
};
开发工具集成
ESLint 集成
javascript
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true // 启用 Babel 缓存
}
},
{
loader: 'eslint-loader',
options: {
fix: true, // 自动修复
emitWarning: true, // 以警告形式显示错误
configFile: './.eslintrc.js'
}
}
]
}
]
}
};
TypeScript 开发配置
javascript
module.exports = {
mode: 'development',
entry: './src/index.tsx',
devtool: 'eval-source-map',
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true, // 只转译,不进行类型检查
happyPackMode: true // 启用 happypack 模式
}
}
],
exclude: /node_modules/
}
]
},
plugins: [
// 使用 ForkTsCheckerWebpackPlugin 进行类型检查
new ForkTsCheckerWebpackPlugin({
typescript: {
diagnosticOptions: {
semantic: true,
syntactic: true
}
}
})
]
};
环境变量配置
开发环境变量
javascript
const webpack = require('webpack');
module.exports = {
mode: 'development',
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV ': JSON.stringify('development'),
'process.env.API_URL ': JSON.stringify('http://localhost:8080'),
'process.env.DEBUG ': JSON.stringify(true),
'__DEV__': JSON.stringify(true),
'__PRODUCTION__': JSON.stringify(false)
})
]
};
使用 dotenv 配置环境变量
javascript
const webpack = require('webpack');
const dotenv = require('dotenv');
// 加载 .env 文件
const env = dotenv.config().parsed;
// 将 .env 中的变量转换为 webpack 需要的格式
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env. ${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
module.exports = {
mode: 'development',
plugins: [
new webpack.DefinePlugin(envKeys)
]
};
开发环境完整配置示例
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
module.exports = {
mode: 'development',
devtool: 'eval-cheap-module-source-map',
entry: {
app: [
'react-hot-loader/patch', // React 热加载补丁
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./src/index.js'
]
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json'
},
devServer: {
contentBase: path.join(__dirname, 'public'),
hot: true,
port: 3000,
open: true,
historyApiFallback: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
},
clientLogLevel: 'none',
overlay: {
warnings: false,
errors: true
}
},
module: {
rules: [
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
browsers: ['last 2 versions']
}
}],
'@babel/preset-react'
],
plugins: [
'react-refresh/babel'
],
cacheDirectory: true
}
}
],
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[local]_[hash:base64:5]'
},
sourceMap: true
}
}
]
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[hash:7].[ext]',
outputPath: 'images/'
}
}
]
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new ReactRefreshWebpackPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html',
filename: 'index.html'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
},
extensions: ['.js', '.jsx', '.json']
},
optimization: {
moduleIds: 'named',
chunkIds: 'named'
}
};
小结
开发环境的配置重点在于提高开发体验和构建速度。关键配置包括启用热模块替换、使用合适的源映射、配置开发服务器、优化构建性能等。合理的开发环境配置能够显著提升开发效率。