面对的问题:
这是一个在微前端项目中遇到的问题。问题是子应用Sub内的jsonp请求在运行时出现跨域。众所周知,jsonp请求是解决跨域的其中一种方式,但是为什么在微前端中使用了jsonp却还是出现跨域问题?
这是简单的项目结构示意。
解决方案
先说解决方案,之后再一起研究达到这个方案的解决路径。下面2个图分别是解决前后的两套代码。
- 解决前,Sub使用自身import的fetchJsonp方法进行请求出现跨域。


- 解决后,Main向Sub传入自身的fetchjsonp方法,同时设置
excludeAssetFilter属性(稍后说明作用)。Sub中使用Main传入的fetchjsonp方法进行请求即可解决问题。

解决方案总结: 实际上为了解决这个问题我们做了两个工作:
- 让Sub使用Main传入的fetchjsonp方法。
- 配置
excludeAssetFilter参数来放行部分资源请求。
分析
在上面的解决方案中我们主要做了两项配置:
1. 使用Main传入的fetchjsonp方法
2. 放行资源请求(相当于一个针对请求域名`api.map.baidu.com`的白名单)
其实从上面两个控制台截图可以看到修改后解决了什么问题:修改之前,qiankun竟然将jsonp请求变成了fetch请求,所以自然会因为违反同源策略跨域。修改后才变成了我们想要的jsonp形式。
实际上这两项配置各自解决了不同的问题,我们来验证一下:
excludeAssetFilter的作用:首先我把第2个配置参数excludeAssetFilter去掉,我们看一下效果:

看上图蓝色圈出的地方,会发现发现代码里写的jsonp请求变成了fetch请求。这其实是qiankun的一个机制:qiankun会把子应用(Sub)里的资源请求(包括css、js资源和请求)全部使用fetch的方式进行请求。当设置了excludeAssetFilter时,相当于给这个域名一个白名单,不使用qiankun的这个机制,所以变回了jsonp请求,跨域问题解决。fetchJsonp={fetchJsonp}的作用:把excludeAssetFilter参数加回来,再把Main中fetchJsonp={fetchJsonp}注释掉。
看一下结果:

请求已成功,数据已返回,但是控制台报红。很费解吧?为啥数据都回来了,控制台却说请求超时?
控制台里面有两种报错,一个是func is not defined,另一个是request timed out。
先看第一个func is not defined,这是jsonp的回调函数执行时候报的提示未定义,看到时候第一时间想到的可能是函数不存在,但实际是并不是不存在,而是在其他位置。即当我们使用Sub自己import的fetchJsonp时,fetchJsonp会把jsonp回调函数定义在子应用自身的环境(也就是我们说的沙箱隔离)中,但回调执行的时候会去window里找这个函数,驴唇对马嘴,就肯定找不到了。至于控制台下面的JSONP request to ... timed out这个报错,是因为fetchJsonp内部没找到回调函数一直等待超过了fetchJsonp设置的超时时间。
所以我们使用的解决方式是Main传给Sub一个fetchJsonp,这样fetchJsonp会把jsonp回调函数定义在window上,回调执行的时候就可以找到定义好的回调了。
所以总结下来:Main给Sub传fetchJsonp解决的是回调函数定义与调用环境统一的问题,excludeAssetFilter解决的是qiankun默认把jsonp换成fetch的问题。这两个设置配合才可以解决最终问题。
这里涉及到了qiankun的JS沙箱机制,待我组织好语言,细细研究再来好好总结一下~
版权声明:本文为qq_37751687原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。