在基于vue-cli的项目自定义打包环境
在工作当中,遇到了下面这个问题:
测试环境与生产环境中的用户权限不一样,因此,就需要根据测试环境打一个包,生产环境又打一个包。
可是,如果每次打包都需要更改权限的配置文件的话,会很麻烦,而且,体现不出一个coder该有的逼格。
为了更有逼格地解决这个问题,于是我百度了一番,上天不负有心人,让我找到了解决方案。
在详叙解决方案之前,先简单介绍下解决方案当中使用到的工具:cross-env,webpack.DefinePlugin
- cross-env是给process.env当中添加变量的,那process.env又是什么呢?
process是一个控制node.js的进程,它是一个global对象,包含进程相关的一些信息,而process.env则是包含用户环境信息的一个对象,例如下面这样的对象:
{ TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'maciej', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/maciej', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/maciej', LOGNAME: 'maciej', _: '/usr/local/bin/node' }
使用cross-env可以往这个process.env对象当中添加自定义的数据,然后可以在任何node.js的执行环境当中获取,一般是在打包配置当中获取process.env.NODE_ENV来判断是哪种环境,然后再作相应的配置。
如何使用cross-env
- 安装:npm i cross-env -D
- 在npm自定义命令当中使用;
"script":{ "build:testing":"cross-env NODE_ENV=‘testing’ webpack" }
然后,我们执行npm run build:testing的时候,就好执行以上的命令,cross-env就会在process.env当中添加一个NODE_ENV的属性,属性的值就是‘testing’字符串,注意这里是加了单引号的,因为这样才是一个字符串,如果不加的话,就相当于一个代码片段,还要在获取完之后通过JSON.stringify去转成字符串。
- webpack.DefinePlugin又是什么呢?
webpack.DefinePlugin是webpack自带的一个插件,它的作用是在编译的时候生成一些全局变量的,这里说的全局变量指的是客户端的全局变量,相当于挂载在window对象上的变量,我们可以利用它的这个功能在不同的环境(开发,测试,或者生产)当中定义不同的行为。
介绍完两个插件了,是时候说一下两者结合在实际当中如何使用了。
下面将展示如何解决本文开头一开始所提到的根据测试和生产环境配置不同的用户权限的问题。
在config目录下,根据不同的环境创建不同的配置文件
如上图所示,test.env.js是测试环境的配置文件,prod.env.js则是生产环境的配置文件
- test.env.js的配置
const merge = require('webpack-merge') const devEnv = require('./dev.env') module.exports = merge(devEnv, { NODE_ENV: '"testing"' })
- prod.env.js的配置
module.exports = { NODE_ENV:"production" }
分别创建测试与生产的权限配置文件
- test.authority.js 测试环境权限
function getAuthority(userAuthority){ const menus = []; switch(userAuthority){ case 'zhangsan': menus = ["a","b","c","d"]; //这里的a,b,c,d相当与路由配置当中页面的name break; case 'lishi': menus = ["a","b","c"]; break; case 'wangwu': menus = ["b","c","d"]; break; default: menus = ["a","b"]; } return menus; } export default getAuthority;
- prod.authority.js 生产环境的配置方法页和上面一样,只不过是menus里的配置不同
使用cross-env配置对应的NODE_ENV
- package.json
"scripts":{ "build:testing": "cross-env NODE_ENV='testing' node build/build.js", "build": "cross-env NODE_ENV='production' node build/build.js" }
npm run build:testing执行的是测试环境的打包,npm run build则是生产环境的打包。
将当前环境的配置添加到客户端全局
- build/webpack.prod.conf.js
const env = process.env.NODE_ENV === 'testing' ? require("../config/test.env.js") : require("../config/prod.env.js"); //配置webpack.DefinePlugin将env添加到全局变量当中 plugins:[ new webpack.DefinePlugin({ "ENV":env }) ]
根据环境信息配置用户权限
要对用户权限进行控制是要先知道当前登录的是哪个用户,因此用户权限配置的操作是在登录页面完成的。
- login.vue
//获取环境信息,然后根据环境信息读取对应的权限配置文件 const env = ENV.NODE_ENV === "testing" ? "test" : "prod"; import getAuthority from `${env}.authority.js`; export default { methods:{ login(){ axios({...}).then(res => { //调用登录接口获取当前用户信息 let userAuthority = getAuthority(res.userName); //获取当前登录用户的页面权限 sessionStorage.setItem("authorityPages",JSON.stringify(userAuthority)) //将用户的页面权限保存起来,在生成侧边栏的时候通过v-if指令判断是否渲染 }) } } }
来到这里,就能够解决本文一开始所提的问题了,下面总结一下。
总结
- 根据不同的环境编写对应的打包环境信息配置文件;
- 根据不同环境编写对应用户权限配置文件;
- 根据不同环境编写对应的npm打包命令,使用cross-env设置对应的运行时环境;
- 在打包配置文件当中根据运行时环境获取对应的环境配置信息,然后使用webpack.DefinePulgin添加到客户端全局变量当中;
- 登录页根据全局变量中的环境信息获取对应的用户权限配置文件;
- 用户登录之后根据获取的用户权限文件中的方法获取登录用户的权限,并把当前登录用户的权限保存起来以便之后使用。