前言:刚接手我们前端这个项目时,项目内部定义两个变量服务器地址和七牛的地址,每次上线,都需要手动去切换这两个地址到生产环境,很不方便。后来,又引入了第三个全局变量,这个时候我就改进了下,专门定义一个环境变量来控制这三个变量的值,这样稍微好了些,但是每次上线还是需要手动去切换,需要非常小心。使用webpack建立开发和生产环境,我们就可以一句命令上线,不用再过多担心。
今天,我们来谈谈在webpack中建立开发和生产环境,下面是我在实践过程中的一些总结,希望给大家能带来一些帮助。
因为webpack的开发和生产命令不同、参数复杂原因,又因为npm scripts定义命令的简便和钩子功能,所以使用npm定义简单统一的命令成为我们的需要(不了解npm scripts的同学可以先看阮一峰老师的 npm scripts 使用指南 )。
如下是我在项目用到的一部分命令:
{
// ...
"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"
}
}
定义好上面内容后:
npm run dev
就相当于运行了
env ENV_MODE=dev webpack-dev-server --hot --inline --progress --colors
注:上面这句命令,设置了一个指定的环境变量去执行webpack-dev-server命令,后面我们可以在 webpack.config.js
中通过 process.env.ENV_MODE
获取它的值。
npm run deploy
它就会首先执行 pre-deploy
中的命令,输出:
******开始构建生产环境的代码*********
然后,执行:
rm -rf dist && ENV_MODE=production webpack --progress --colors --bail --profile
开始打包代码到 dist
目录下。
最后,打包完成之后,它会执行 post-deploy
中的命令:
echo '******构建成功,开始发布内容*****' && chmod +x publish.sh && ./publish.sh build-master
首先输出:
******构建成功,开始发布内容*****
之后,给当前目录下的 publish.sh
脚本添加执行权限,并传递 build-master
给 publish.sh
执行。
publish.sh
的作用是发布上线,它做的事情主要是将 dist
中打包好的代码强制发布到对应的分支下,然后服务器利用git的 post-receive
钩子自动同步代码到对应目录下,这样就达到了发布上线。
脚本代码如下:
#!/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 git@github.com: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
,内部的 git@github.com:liuchungui/AngularWebpack.git
可以替换为你的git仓库地址。
上面的脚本执行,会定义一个环境变量 ENV_MODE
,而我们可以在 webpack.config.js
文件中获取它的值,然后通过 DefinePlugin
插件配置到我们项目中使用,从而达到自动配置开发或生产环境,不需要我们手动设置。
如何配置呢?代码如下:
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
替换成我们传递给它的值。
这样,我们就可以在代码中像下面这样获取服务器地址:
// 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
的值。
这里并不是说只有某个环境才能使用,只是强烈建议在某个环境下使用。如代码压缩我们应该只在生产环境下使用,开发环境下使用会影响开发效率,下面是我的一些配置:
//生产环境下独有的插件
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()
// );
}