# 生产环境构建
# 1. 配置
开发环境(development)和生产环境(production)的构建目标差异很大。在开发环境中,我们需要具有强大的、具有实时重新加载(live reloading)或热模块替换(hot module replacement)能力的 source map 和 localhost server。而在生产环境中,我们的目标则转向于关注更小的 bundle,更轻量的 source map,以及更优化的资源,以改善加载时间。由于要遵循逻辑分离,我们通常建议为每个环境编写彼此独立的 webpack 配置。
虽然,以上我们将生产环境和开发环境做了略微区分,但是,请注意,我们还是会遵循不重复原则(Don't repeat yourself - DRY),保留一个“通用”配置。为了将这些配置合并在一起,我们将使用一个名为 webpack-merge 的工具。通过“通用”配置,我们不必在环境特定(environment-specific)的配置中重复代码。
我们先从安装 webpack-merge 开始,并将之前指南中已经成型的那些代码再次进行分离:
# npm install --save-dev webpack-merge
# + 项目架构
webpack-demo
| - package.json |
| -------------- ||webpack.config.js
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
|- /dist
|- /src
|- index.js
|- math.js
|- /node_modules
2
3
4
5
6
7
8
9
10
11
# + webpack.common.js
const path = require("path");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
app: "./src/index.js",
},
plugins: [
new CleanWebpackPlugin(["dist"]),
new HtmlWebpackPlugin({
title: "Production",
}),
],
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "dist"),
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# + webpack.dev.js
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
devtool: "inline-source-map",
devServer: {
contentBase: "./dist",
},
});
2
3
4
5
6
7
8
9
# + webpack.prod.js
const merge = require("webpack-merge");
const UglifyJSPlugin = require("uglifyjs-webpack-plugin");
const common = require("./webpack.common.js");
module.exports = merge(common, {
// 生产环境中使用source-map
devtool: "source-map",
plugins: [
new UglifyJSPlugin({
sourceMap: true,
}),
],
});
2
3
4
5
6
7
8
9
10
11
12
13
# 2. NPM Scripts 配置
# - package.json
"scripts": {
"start": "webpack-dev-server --open --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
}
2
3
4
# 3. 生产环境和开发环境的 环境变量是可以更换的
当使用 process.env.NODE_ENV === 'production' 时,一些 library 可能针对具体用户的环境进行代码优化,从而删除或添加一些重要代码。我们可以使用 webpack 内置的 DefinePlugin 为所有的依赖定义这个变量:
# webpack.prod.js
const webpack = require("webpack");
const merge = require("webpack-merge");
const UglifyJSPlugin = require("uglifyjs-webpack-plugin");
const common = require("./webpack.common.js");
module.exports = merge(common, {
devtool: "source-map",
plugins: [
new UglifyJSPlugin({
sourceMap: true,
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production"),
}),
],
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
技术上讲,NODE_ENV 是一个由 Node.js 暴露给执行脚本的系统环境变量。通常用于决定在开发环境与生产环境(dev-vs-prod)下,服务器工具、构建脚本和客户端 library 的行为。然而,与预期不同的是,无法在构建脚本 webpack.config.js 中,将 process.env.NODE_ENV 设置为 "production",请查看 #2537。因此,例如 process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js' 这样的条件语句,在 webpack 配置文件中,无法按照预期运行。
还要注意,任何位于 /src 的本地代码都可以关联到 process.env.NODE_ENV 环境变量