2020-04-10 百度地图api和qiankunjs的script劫持引起的问题

首先,我们梳理一下百度地图加载的过程。

我们在页面的html底下写了一条百度地图的script,页面在初始化的时候,会加载这条script,这条script会引入BMap这个全局变量,以及一些处理函数(比如我们下面要讲到的_jsload2),然后会检测localstorage里面有没有需要的一些变量,没有的话,再次写一个标签,形如api.map.baidu.com/getmodules?这样src的script,由于是script标签引入的,所以没有跨域的问题,这条脚本会加载一条条函数,放到全局window底下去实现,把一些处理函数放到localstorage里面。

接着有趣的事情发生了,由于qiankunjs用了自己写的import-html-entry来劫持script标签,把这条标签注视掉,然后发起一个通用的fetch来请求这些资源,这样就导致了那些用script标签引入的资源会导致跨域错误。

可以的解决办法:看了源码,发现在用qiankunjs启动的时候,跨域传入一个opts参数,这条参数,可以写入一个fetch请求,如果没有这个fetch,则使用浏览器自带的fetch,这个地方就给我们留了条口子来hack

说干就干,针对那些有callback的src,我们就可以认为他是jsonp请求,这部分我们拆开来处理,其余的则按照fetch来处理,这里需要注意的是fetchjsonp会写一条标签,这个标签我们得放到document底下,不然依然会被qiankunjs劫持,导致死循环。这样的话,依然会发生上面跨域的问题,为什么呢?原因在于形如api.map.baidu.com/getmodules?这样的标签是没有callback参数的,编者认为可能百度也就不是按照jsonp的请求来实现的,而是仅仅是写一条标签,引入这个资源罢了,但是我们还是按照统一的jsonp来封装请求他。

请求得到的内容,其中就有我上面说的_jsload2

这里有一个_jsload2,这个其实是一开始的百度标签所加载的一个全局函数,写入了window底下,原本,检测出了localstorage里没有相应的内容,即会加载这几条js,来依次写入相应的内容,但是,这个地方,我们犯了个错,本意是想改写_jsload2这个函数,让其能够实现原本功能外,还能监测到其执行的状态,但是,这里犯了个错,这个函数,的参数有两个,但是我们只写了一个,导致后面的内容变成了undefined,从而后续结果报错,这里编者之前还有点纠结一个问题,即换了名字可以成功请求,使用_jsload2却不能成功,后来经过查验发现,由于使用的名字不是_jsload2,但是返回的依然是_jsload2,导致不能访问到我们自定义的callback,然后导致超时,抛出了自定义错误,由于没有捕获,所以我们查看不到,另一方面,虽然导致了自定义错误,但是,由于使用fetchjsonp,这条标签其实是写到document底下的了,然后就自然的加载了资源,在全局window底下执行_jsload2这个函数,未改其名字前,由于写入的参数错误,导致第二个参数成了undefined,导致写入localstorage错误,从而导致后续错误。


总结:这次事件首先我对百度地图加载资源就不太清楚,开始就没有发现是localstorage的问题,然后梳理了一下百度地图加载过程之后,这个事情其实也就比较清楚了,解决方案因人而异,这里是我们的解决方案,并且因此导致的一些问题,谨作记录!

你可能感兴趣的:(2020-04-10 百度地图api和qiankunjs的script劫持引起的问题)