前言:刚接手我们前端这个项目时,项目内部定义两个变量服务器地址和七牛的地址,每次上线,都需要手动去切换这两个地址到生产环境,很不方便。后来,又引入了第三个全局变量,这个时候我就改进了下,专门定义一个环境变量来控制这三个变量的值,这样稍微好了些,但是每次上线还是需要手动去切换,需要非常小心。使用webpack建立开发和生产环境,我们就可以一句命令上线,不用再过多担心。

今天,我们来谈谈在webpack中建立开发和生产环境,下面是我在实践过程中的一些总结,希望给大家能带来一些帮助。

1、定义npm scripts的开发和生产命令,自动打包上线

因为webpack的开发和生产命令不同、参数复杂原因,又因为npm scripts定义命令的简便和钩子功能,所以使用npm定义简单统一的命令成为我们的需要(不了解npm scripts的同学可以先看阮一峰老师的npm scripts 使用指南)。

如下是我在项目用到的一部分命令:

1
2
3
4
5
6
7
8
9
10
11
{
// ...
"scripts": {
"dev": "env ENV_MODE=dev webpack-dev-server --hot --inline --progress --colors",
"predeploy": "echo '******开始构建生产环境的代码*********'",
"deploy": "rm -rf dist && ENV_MODE=production webpack --progress --colors --bail --profile",
"postdeploy": "echo '******构建成功,开始发布内容*****' && chmod +x publish.sh && ./publish.sh build-master"
}
}

定义好上面内容后:

我们在开发时,只需要运行:

1
npm run dev

就相当于运行了

1
env ENV_MODE=dev webpack-dev-server --hot --inline --progress --colors

注:上面这句命令,设置了一个指定的环境变量去执行webpack-dev-server命令,后面我们可以在webpack.config.js中通过process.env.ENV_MODE获取它的值。

我们需要打包发布上线时,只需要运行:

1
npm run deploy

它就会首先执行pre-deploy中的命令,输出:

1
******开始构建生产环境的代码*********

然后,执行:

1
rm -rf dist && ENV_MODE=production webpack --progress --colors --bail --profile

开始打包代码到dist目录下。

最后,打包完成之后,它会执行post-deploy中的命令:

1
echo '******构建成功,开始发布内容*****' && chmod +x publish.sh && ./publish.sh build-master

首先输出:

1
******构建成功,开始发布内容*****

之后,给当前目录下的publish.sh脚本添加执行权限,并传递build-masterpublish.sh执行。

publish.sh的作用是发布上线,它做的事情主要是将dist中打包好的代码强制发布到对应的分支下,然后服务器利用git的post-receive钩子自动同步代码到对应目录下,这样就达到了发布上线。

脚本代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env bash
cd dist
echo $1
#构建代码不能放入打包的代码中
if [ x"$1" == x"" -o "$1" == "dev" -o "$1" == "master" -o "$1" == "test" -o "$1" == "simulate" ]; then
echo "代码分支,不要构建"
exit -1
fi
echo "##### clean git"
rm -rf .git
echo "##### 初始化git"
git init
git add .
git commit -m "update at `date` "
git remote add origin [email protected]:liuchungui/AngularWebpack.git >> /dev/null 2>&1
echo "##### push到$1分支"
git branch $1
git checkout $1
git push origin $1 -f
echo "##### $1 发布完成"

建了一个demo,大家可以下载下来看看AngularWebpack,内部的[email protected]:liuchungui/AngularWebpack.git可以替换为你的git仓库地址。

2、定义ENV_MODE变量,配置环境

上面的脚本执行,会定义一个环境变量ENV_MODE,而我们可以在webpack.config.js文件中获取它的值,然后通过DefinePlugin插件配置到我们项目中使用,从而达到自动配置开发或生产环境,不需要我们手动设置。

如何配置呢?代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = function makeWebpackConfig() {
/**
* 创建配置对象
*/
var config = {};
// ... 省略其它代码
config.plugins = [];
config.plugins.push(
//配置环境变量
new webpack.DefinePlugin({
ENV_MODE: JSON.stringify(process.env.ENV_MODE),
})
);
return config;
}();

注意: JSON.stringfy一定不能省略,DefinePlugin插件的作用是将打包的变量ENV_MODE替换成我们传递给它的值。

这样,我们就可以在代码中像下面这样获取服务器地址:

1
2
3
4
5
6
7
8
9
// common.js文件
function serverBaseURL() {
switch (ENV_MODE) {
case "dev": return "http://localhost/api/";
case "production": return "http://api.xxx.com/";
default: return "http://localhost/api/";
}
}
module.exports = serverBaseURL();

当然,你也可以直接使用DefinePlugin定义ServerBaseURL的值。

3、只有开发或生产环境应该使用的插件

这里并不是说只有某个环境才能使用,只是强烈建议在某个环境下使用。如代码压缩我们应该只在生产环境下使用,开发环境下使用会影响开发效率,下面是我的一些配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//生产环境下独有的插件
if (isProd) {
config.plugins.push(
new webpack.NoErrorsPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin(),
new CopyWebpackPlugin([
{
from: __dirname + '/gw/images',
to: __dirname + '/dist/gw/images'
}
])
}
//开发环境下使用的插件
else {
// config.plugins.push(
// new WebpackBrowserPlugin()
// );
}

总结

主要说了我们应该定义开发和生产环境的命令,方便我们使用;之后,说了通过DefinePlugin插件定义开发和生产环境的变量;最后,列出了一些应该在生产环境中使用的插件。

参考

angular-webpack

webpack多页应用架构系列(七):开发环境、生产环境傻傻分不清楚?

npm scripts 使用指南