拆分生产环境和开发环境配置
约 1762 字大约 6 分钟
2025-03-15
Webpack 是现代前端开发中最流行的模块打包工具之一,它提供了两种主要的构建模式:开发模式(development)和生产模式(production)。这两种模式针对不同的使用场景进行了优化。
开发模式 development
开发模式是为开发环境设计的,主要关注以下几点:
- 构建速度优化:快速重新构建,提高开发效率
- 调试友好:提供完整的源代码映射(source maps)和错误提示
- 开发工具集成:支持热模块替换(HMR)等功能
主要特点
- 不压缩代码:保留原始格式,便于调试
- 包含完整的 source maps:可以精确追踪到源代码中的错误位置
- 保留开发辅助代码:如警告、注释等
- 启用 HMR(热模块替换):修改代码后无需完全刷新页面
- 更详细的错误信息:提供完整的错误堆栈跟踪
- 使用内存编译:提高重新构建速度
配置方式
// webpack.config.js
module.exports = {
mode: "development",
// 其他配置...
};
或在命令行中:
webpack --mode development
生产模式 (production)
生产模式是为最终部署到线上环境设计的,主要关注:
- 代码优化:最小化文件体积,提高加载速度
- 性能优化:优化运行时的性能
- 去除开发专用代码:减少不必要的代码
主要特点
- 代码压缩:使用 TerserWebpackPlugin 等工具压缩 JS 代码
- 作用域提升(Scope Hoisting):优化打包后的模块结构
- Tree Shaking:移除未使用的代码
- 资源优化:压缩图片、提取 CSS 等
- 去除 source maps(或使用简化的 source maps)
- 去除开发专用代码:如 console.log、调试工具等
- 启用更多性能优化:如模块合并、缓存优化等
配置方式
// webpack.config.js
module.exports = {
mode: "production",
// 其他配置...
};
或在命令行中:
webpack --mode production
两种模式的主要区别
特性 | 开发模式 (development) | 生产模式 (production) |
---|---|---|
构建速度 | 快 | 较慢(因为要做更多优化) |
代码压缩 | 不压缩 | 压缩 |
Source Maps | 完整、高质量的 source maps | 无或简化 source maps |
错误提示 | 详细错误信息 | 简化错误信息 |
热更新(HMR) | 支持 | 不支持 |
Tree Shaking | 不启用 | 启用 |
作用域提升 | 不启用 | 启用 |
调试友好度 | 高 | 低 |
输出文件大小 | 较大 | 最小化 |
Babel 优化 | 不优化 | 优化(如移除 prop-types) |
process.env.NODE_ENV | 'development' | 'production' |
高级配置技巧
判断当前环境
// webpack.config.js
module.exports = (env, argv) => {
const isProduction = argv.mode === "production";
return {
// 根据isProduction配置不同的选项
devtool: isProduction ? "source-map" : "eval-cheap-module-source-map",
// 其他配置...
};
};
环境变量注入
可以使用 DefinePlugin 来注入环境变量:
const webpack = require("webpack");
module.exports = {
// ...
plugins: [
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify(
process.env.NODE_ENV || "development"
),
}),
],
};
开发模式主要是为了开发环境设计的,生产模式主要是为了生产环境设计的。
为了适配不同的环境,我们可以拆分成两个配置文件来放不同的配置。
文件目录
webpack-test# 项目根目录
config# Webpack 配置文件目录
webpack.dev.js# 开发模式配置文件
webpack.prod.js# 生产模式配置文件
node_modules# 下载包存放目录
…
public# 项目 html 文件
index.html
src# 项目源码目录,除了 html 其他都在 src 里面
main.js# 项目入口文件
.eslintrc.js# Eslint 配置文件
babel.config.js# Babel 配置文件
package.json# 包的依赖管理配置文件
webpack.dev.js
以下是一份相对完整的开发模式配置文件
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/main.js",
// 开发模式
output: {
path: undefined, // 开发模式没有输出,不需要指定输出目录
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
// clean: true, // 开发模式没有输出,不需要清空输出结果
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
],
// 其他省略
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
},
mode: "development",
};
运行开发模式的指令:
npx webpack serve --config ./config/webpack.dev.js
webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
运行生产模式的指令:
npx webpack --config ./config/webpack.prod.js
4. 配置运行指令
为了方便运行不同模式的指令,我们将指令定义在 package.json 中 scripts 里面
// package.json
{
// 其他省略
"scripts": {
"start": "npm run dev",
"dev": "npx webpack serve --config ./config/webpack.dev.js",
"build": "npx webpack --config ./config/webpack.prod.js"
}
}
以后启动指令:
- 开发模式:
npm start
或npm run dev
- 生产模式:
npm run build
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于