开发背景:
(资料图片仅供参考)
日常经常需要切换到不同伙伴开发的接口上,例如还未提交/不能提交的接口,或是协助断点调试等等,戳中打1。
线上服务器撞山垮塌崩,没有HS需要改接口地址,重新pack发版都嫌慢的,戳中打2。
本方案目前只在Vue的2和3两个上使用过,其他需要打包的框架应该也能类比吧,没一一测试,无框大佬鄙人帮不上的就只能谢谢点赞了。
知识点:
原生XMLHttpRequest,localStorage,async/await或Promise
方案思路:
打包的项目由于配置是一起被固化到了代码内,所以想要变更这些固定配置,但不重新打包,需要将这些写好的配置改为通过其他途径去获取,那么数一下前端能够自力更生的方案里,new一个XMLHttpRequest去拉配置是最简单的。
配置的获取方式确定了,就需要再确定一个获取的时点,想想Vue在每个访问连接打开发生时候都干了啥(不是指tcp握手之类的ho~),访问到index,new一个vue实例,那么跑去main看看,好,里面还是有可以创作的空间的,那么我们就可以在Main脚本里执行我们拉配置的方法。
现在剩下的问题就是怎么把dev环境的proxy以及prod下的接口地址改成动态的,还是回到项目代码里,找到相关的两处来分析,首先解决dev的,以vite为例子,vite配置里的{ server }节点的proxy,即是配置接口目标代理的位置,通常就是写一个target/rewrite即可,如果是多个目标地址,建议采用一个单独的脚本去生成,稍后下文会上具体代码。其次prod的,由于生产环境下一般不走proxy(KOA服务进行代理的不算),所以只需要关注如何改变BaseURL即可(我默认是用Axios哈,其他的请求库或者手写的请求器也类似,关注如何改变接口地址域名),同样稍后会有具体代码伺候。整个方案其实都很Easy来的,都是一些基础内容。
Coding过程:
下面都是Vue3的例子,Vue2也能用,但是文件位置等可能会有变化,我这里没用TS(别问为什么不TS,问就是不会),而且项目结构是按照个人习惯来的,不建议照搬,搞代码一定要魂,要有自己的风格。
涉及到改动的两个固定文件:vite.config.js,main.js;
需要增加的代码块:负责生成dev环境下的proxy清单的方法,负责获取配置的方法;
额外增加的配置文件两个,分别对应development和production两个环境。
分别按照步骤一一说明:
首先创建一个负责生成dev环境下的proxy清单的方法的模块
这段代码的作用就是给vite.config.js获取代理配置所用,targets为需要对接的所有服务器地址,也可以用好辨识的名字,比如我实际上用的就是其他伙伴姓名的拼音缩写;generateProxySetting是根据targets的内容遍历key,并根据key的名称生成proxy数据组,proxies为存放生成的proxy数据的空对象,也可以预设需要的数据,比如我在这里放的就是mock接口数据;useProxyTable则是最终将targets给处理成可用的proxy数据的方法,把上述内容组织起来,并导出useProxyTable方法备用。
接下来是vite.config.js的改动
然后需要创建配置的JSON文件
配置文件需要创建到项目的public下,以便项目能够在打包后可以正常加载到(public作为vue项目的静态资源应该都知道吧),比如我是使用的public/config路径(config自己创建)
这里配置文件的命名建议里面包含环境的标识符,譬如development/production这种(稍后你就知道为啥了,问就是就是懒)。
再就是获取配置文件的方法
图思:根据当前打包环境匹配到需要使用的json文件名,然后通过ajax获取到配置,再存到缓存里,整体需要考虑到一个异步顺序问题;我数据暂存用的pinia,类似vuex的功能,如果项目里面没有用到store概念的,可以直接存localStorage/sessionStorage,只要能让后续调用出来就成。
还是一个个的来讲:envString为当前的环境标识(vite的写法),webpack获取途径可能会不一样;bootFileUrl为配置文件的存放位置,供ajax使用;getConfig为获取配置文件的方法,原始的ajax写法,然后输出一个返回对象,我这里是为了和后台接口格式统一所以附加了几个字段;boot为输出供Main.js调用的方法,负责调用getConfig获取配置并存到缓存,这里为了确保异步顺序,使用async/await来控制并确保各个步骤完成。
boot方法是整个的核心,这里主要是将你的JSON内容转换成对象,并储存在对应的缓存区内,如果你用了状态管理,在后续就直接使用状态管理提供的值就好;如果使用的是Storage类的,则切记获取时候JSON.parse一下ho~
Main.js的改动
快完了快完了…Main.js的作用不赘述了,很适合搞一些创作在里面的,这里需要改动的就是加入获取配置方法的调用,还是直接上图
我这里是在createApp后调用的boot,因为我需要预先初始化store里面的内容,故app要先行创建(pinia的状态管理模块需要这样,具体可以参考下pinia的文档,此处说个题外话,pinia虽然新但是API类似vuex,而且提供了hooks写法,也支持函数实例化,所以用起来较vuex顺手)。
注意:await boot()这里,如果编译不过去,请参考top-level-await这个关键词的相关搜索,可能需要安装一个模块。
请求封装文件的改动
好累,最后一步了,我就直接放出我的代码吧,其他的封装方式大同小异,都是集中在获取缓存,然后组装实际访问地址
打完收工,我们看看实际访问时候的效果
DEV环境下
这里利用了devServer的proxy特性,然后设置proxies里面对应的key就能转换出相应的主机地址。
PROD环境下
这里缓存的就是直接的地址了,由于生产环境没有使用proxy,所以请求封装那里就会直接使用这个配置里的信息,后面的图就不上了。
以上,欢迎提问和反驳,互通有无。
关键词:
AJAX
BOOT
SERVER
PROMISE
互通有无
JSON
CODING
Prod
PACK
WEBPACK
TARGET
MAIN
easy
vue2
INDEX
自力更生
A_PI