前言:刚接手我们前端这个项目时,项目内部定义两个变量服务器地址和七牛的地址,每次上线,都需要手动去切换这两个地址到生产环境,很不方便。后来,又引入了第三个全局变量,这个时候我就改进了下,专门定义一个环境变量来控制这三个变量的值,这样稍微好了些,但是每次上线还是需要手动去切换,需要非常小心。使用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() // ); }