使用Wujie时遇到的mathjax加载问题
07:04
阅读次数: 0最近项目使用wujie进行重构,但是遇到了一些问题。
原来的项目引入了mathjax来进行数学公式的展示,但是,在作为wujie的子应用的时候。mathjax
无法成功加载。
先看看老项目是怎么加载的:
<script type="text/x-mathjax-config"> MathJax.Hub.Config({ jax: ['input/TeX', 'output/HTML-CSS', 'output/SVG'], messageStyle: 'none', displayAlign: 'left', skipStartupTypeset: true, }); </script> <script src="https://oss.example.cn/mathjax/mathjax_config.js?rev=1.0.7"></script> <script src="https://oss.example.cn/mathjax/MathJax.js?config=TeX-AMS_HTML"></script>
在head中引入MathJax
的时候,src后面有参数config=TeX-AMS_HTML
。在普通项目中,这个参数是可以被mathjax读取到的。但是放到wujie中 ,config
参数就无法读取了
那是因为wujie本身的加载外部脚本的机制导致的。
wujie 的加载
在wujie启动子应用的加载过程时,所有内联的脚本,都会被替换到iframe中。
wujie的沙箱原理,就是通过iframe运行js脚本,劫持js脚本中的dom变化,反应到wujie自己的webcomponent
中 。
在wujie中,点开控制台就可以看到wujie的结构。
上面的webcomponent
才是最终展示在页面上的。
点开webcomponent
内部的header,可以看到,这里面的都是老应用的head中的一些脚本,而script标签,都会被替换,变成了一个注释:
注释中写明了replaced by wujie。
这是因为js脚本是不会让他在webcomponent
内执行的。最终js脚本都会在iframe内执行。点开iframe的head,可以看到内部的script已经有了之前被替换掉的脚本。
这样,wujie实现了把js放在一个沙箱内执行,而不影响其他的应用。
wujie沙箱的问题
但是,iframe和webcomponent
配合实现的沙箱肯定不是万无一失的。
在一些老旧的脚本中,经常会通过扩展head来实现script的动态加载。
其实这样wujie也是会把script替换到iframe中的,但是卸载的时候,就会出现问题。
因为wujie已经代理了document对象,所有对document的操作,都会映射到webcomponent
中,所以webcomponent
中的script已经找不到了,变成了一串注释。
在这种情况下,只能通过设置jsignore,这个插件可以让wujie放弃代理document对象,所有的操作,又会回到iframe中。
但是又有一个棘手的情况,比如这次的mathjax。
mathjax 的加载过程
在mathjax的加载过程中,会读取src中的config参数,但是,通过我的调试发现,wujie替换之后,无法读取到config参数了。通过上面的wujie加载过程,可以看到,script标签中并没有保留config参数。
mathjax加载时,会首先从页面的所有script中寻找Mathjax脚本,就是通过src判断是否相等,但这个时候,通过document查询script,会查到原来 的webcomponent
里面。
script都没了,全变成注释了,这样还让mathjax怎么找config参数呢,没有了config参数,mathjax就开始自顾自的执行默认配置加载逻辑了,左下角还会出现加载message,还会显示加载失败!!!
找到问题的大致原因,就可以进行改进了,这里可以用wujie进行脚本替换,直接通过jsLoader
插件,替换mathjax中出问题的代码,就是上面的b=(document.documentElement||document).getElementsByTagName("script");
{ jsLoader: (code: string, url: string) => { // 修复mathjax的脚本加载问题 if (url.includes("mathjax")) { return code .replace( 'b=(document.documentElement||document).getElementsByTagName("script");', 'b = __WUJIE_RAW_WINDOW__.document.getElementsByTagName("script");', ) } return code; }, },
替换之后,mathjax加载脚本,就会从iframe中获取script。