当前位置: 首页 > 后端技术 > Node.js

【VueCLI3】环境变量和模式配置实践及源码分析

时间:2023-04-03 19:41:59 Node.js

在官方文档中我们可以看到,熟悉的config目录在新版VueCLI中已经被移除。比如在prod.env.js中,我们会这样配置:'usestrict'module.exports={NODE_ENV:'"production"'}而在代码中,也可以使用process.env.NODE_ENV来判断一些环境代码。在新建VueCLI项目中,我们通常会在项目根目录下放置几个文件:.env.development.env.production符合官方文档中提到的以下模式:.env.[mode]#中加载的内容指定的mode不是之前的对象,而是key=valueVUE_APP_API_PREFIX=http://****我们在执行vue-cli-service的时候会用到:lib/Service.js文件中的init函数:init(mode=process.env.VUE_CLI_MODE){//加载模式.envif(mode){this.loadEnv(mode)}//加载基础.envthis.loadEnv()}我们来看看loadEnv(mode){constbasePath=path.resolve(this.context,`.env${mode?`.${mode}`:``}`)constlocalPath=`${basePath}.local`constload=path=>{}}在加载函数中:constres=loadEnv(path)这里的loadEnv来自于:util/loadEnv.js文件constloadEnv=require('./util/loadEnv')我们看一下文件内部:依赖于fs模块constfs=require('fs')暴露了一个函数loadEnv,接受一个参数path,默认值为'.env'最后赋值给process.envmodule.exports=functionloadEnv(path='.env'){constconfig=parse(fs.readFileSync(path,'utf-8'))Object.keys(config).forEach(key=>{if(typeofprocess.env[key]==='undefined'){process.env[key]=config[key]}})returnconfig}parse作用是对上面提到的key=value进行处理,具体如下:使用换行符循环,使用正则表达式匹配内容functionparse(src){constres={}src.split('\n').forEach(line=>{//匹配'KEY=VAL'中的'KEY'和'VAL'constkeyValueArr=line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/)//匹配了吗?if(keyValueArr!=null){constkey=keyValueArr[1]letvalue=keyValueArr[2]||''//在引用值中扩展换行符constlen=value?value.length:0if(len>0&&value.charAt(0)==='"'&&value.charAt(len-1)==='"'){value=value.replace(/\\n/gm,'\n')}//删除任何周围的引号和多余的spacesvalue=value.replace(/(^['"]|['"]$)/g,'').trim()res[key]=value}})returnres}使用时注意只只有以VUE_APP_开头的才可以使用。先看一下代码实现原理:cli-service/lib/util/resolveClientEnv.js一开始定义了一个正则:constprefixRE=/^VUE_APP_/对外暴露了一个函数:resolveClientEnv接受2个参数:optionsandrawmodule.exports=functionresolveClientEnv(options,raw){constenv={}Object.keys(process.env).forEach(key=>{if(prefixRE.test(key)||key==='NODE_ENV'){env[key]=process.env[key]}})env.BASE_URL=options.baseUrlif(raw){returnenv}for(constkeyinenv){env[key]=JSON.stringify(env[key])}return{'process.env':env}}env默认是一个对象,循环process.env分解成几个部分:匹配prefixRE.test(key)orkey总是使用NODE_ENV的BASE_URL:env.BASE_URL=options.baseUrl这个函数会用到2个地方,这里只提业务代码相关的一个:cli-service/lib/config/app.js看我们之前的webpack-chain文章应该很熟悉:constresolveClientEnv=require('../util/resolveClientEnv')webpackConfig.plugin('define').use(require('webpack/lib/DefinePlugin'),[resolveClientEnv(options)])它将是webpack.DefinePlugin静态嵌入到业务代码中