盘点一下用了这么长时间遇到的Wujie 无界微前端的坑
目前也用无界微前端很长时间了,当时选择无界没有选择乾坤的原因就是无界的保活模式更加丝滑,客户就想要这种方式,但是在这段过程也遇到了很多问题,甚至有些就是无界目前解决不了的问题,所以希望大家今后遇到了也能提前避免
已经解决的问题
1、子应用使用wangEditor 在主应用中无法编辑 ,无法粘贴,工具栏无法正常使用
✨问题复现
- 子项目中正常
- 主项目无法选中,无法粘贴
✨出现这种问题的原因:
- 子应用运行在 iframe内,dom在主应用的shadowdom中,当选中文字时,在主应用监听selectionchange,并且通过 document.getSelection()获取选中的selection,在wangEditor中 会判断这个 selection instanceof window.Selection,很明显主应用的selection 不可能是 iframe 里面window Selection的实例,所以出现了问题
- shadowDom 大坑,在shadowDom中 Selection.isCollapsed永远为true,相当于永远没有选中,所以只能修改 wangEditor 的代码,让读取 isCollapsed 修改成 baseOffset 和 focusOffset的对比,就知道是否选中了文字了
✨解决方案
1、将 wangeditor 替换成 wangEditor-next,因为wangeditor 作者大大已经说因为种种原因后面不会再继续更新了,所以担心更新的同学可以使用 wangEditor-next 这个还有人在继续更新
2、直接替换一个富文本组件 vue-quill,我使用的就是这个,因为我们项目对富文本的需求没有那么重,只要能用就行,所以你也可以替换一个在无界中没有问题的富文本组件
3、由此我们知道了在无界中getSelection是有问题的 如果遇到了可以用这个插件尝试解决 wujie-polyfill.github.io/doc/plugins…
2、子应用使用vue-office 的 pdf 预览,在主应用中白屏
✨问题复现
- 子应用 正常显示
- 主应用直接加载不出来
✨解决方案:
直接换个轮子,因为vue-office 源码不对外开放,你根本不知道是它内部做了何种处理,所以最好的办法就是直接换个其他的能够预览pdf 的方式,我这边选择的是 kkfile 的方式,kkfile 不仅可以预览pdf 还可以预览很多其他的格式的文件,让后端去生成预览地址 然后前端直接用 iframe 去打开即可
3、开发环境下 vite4 或者 vite5 子应用的 element-plus的样式丢失或者自己写的:root 不生效
✨问题复现
- 子应用正常
- 主应用样式丢失
✨出现这种问题的原因:
主要的原因是因为子应用的 :root 失效了,因为无界中是将:root 转成了:host ,但是如果你是在main.js 中外链的样式
import 'element-plus/dist/index.css'
这样的话无界将无法劫持到将 :root 转成:host
✨解决办法:
增加插件
<WujieVue
width="100%"
height="100%"
name="pro1"
:url
:sync="true"
:exec="true"
:alive="true"
:props="{ jump }"
:plugins="[{
patchElementHook(element, iframeWindow) {
if (element.nodeName === "STYLE") {
element.insertAdjacentElement = function (_position, ele) {
iframeWindow.document.head.appendChild(ele);
};
}
},
}]"
></WujieVue>
如果不生效请清除缓存重新启动,多试几次就行
4、el-select 位置偏移以及 el-table tootip 位置偏移的问题
✨问题复现:
✨出现这种问题的原因:
el中依赖了poper.js 的fixed定位偏移,子应用的dom
挂载在shadowRoot
上,导致计算错误
官网解决办法
试了,发现没啥用,所以维护官网的大大请更新快点,要不然哪个还想用无界啊!!
✨最后解决办法:
使用插件 wujie-polyfill.github.io/doc/plugins…
// import { DocElementRectPlugin } from "wujie-polyfill";
<WujieVue
width="100%"
height="100%"
name="xxx"
:url="xxx"
:plugins="[DocElementRectPlugin()]"
></WujieVue>
我的element-plus 的版本:"element-plus": "^2.9.0",
这个版本比较新,如果你们使用的是比较老的版本或者使用的是element-ui的话,上面的插件可能不生效,可以看下面的解决方案
总结下来无非是几个办法,要么是改element-ui 中的源码,然后在项目中打补丁
要么直接在子应用加代码
body{position: relative !important}
.el-popper {position: absolute !important}
大家都可以都试一下,说不准哪个生效了
5、异步获取e.target 的 e.target 变成了 wujie-app
✨问题复现:
官网文档方法
上面尝试了不行
✨最后解决办法:
使用 插件 wujie-polyfill.github.io/doc/plugins…
import { EventTargetPlugin } from "wujie-polyfill";
// vue
<WujieVue
width="100%"
height="100%"
name="xxx"
:url="xxx"
:plugins=“[EventTargetPlugin()]”
></WujieVue>
完美解决
6、全局样式污染了子应用元素的样式
✨问题复现:
✨最后解决办法:
比如主项目中你给 html 或者 body 文字居中,在子项目中也会受影响,其实这个不算是框架的问题,因为你写了这个是全局样式,那就说明了这个会影响所有的,所以建议大家样式尽量写scope 并且对全局的样式尽量主项目和子项目同步,不要出现不一样的情况,要不然很难去排查这种问题
目前还没找到解决办法的问题:
1、自定义事件
很多项目集成了第三方sdk 比如埋点、错误监控、数据通信,其中sdk 可能会使用了js 的自定义事件,这个时候在子组件中会失效
✨问题复现:
const customEvent = new CustomEvent('update', {
bubbles: true,
composed: true,
detail: {
msg:'我的数据更新喽'
}
})
setTimeout(() => {
console.log(window.__WUJIE_RAW_WINDOW__,'window.__WUJIE_RAW_WINDOW__');
window.dispatchEvent(customEvent)
window.__WUJIE_RAW_WINDOW__ && window.__WUJIE_RAW_WINDOW__.dispatchEvent(customEvent)
}, 2000)
window.addEventListener('update', function(event) {
// 主应用没有反应,子组件中正常
console.log(event)
})
window.__WUJIE_RAW_WINDOW__ && window.__WUJIE_RAW_WINDOW__ .addEventListener('testEvent', function(event) {
// 主应用没有反应,子组件中正常
console.log(event)
})
会发现使用 window.addEventListener 或者 window.WUJIE_RAW_WINDOW .addEventListener 都没有用
✨出现这种问题的原因:
看了issue中作者说这个是无界中的bug ,所以如果有子组件用到这个自定义事件的,只能先将子组件用iframe 嵌入进去,等作者更新了再改回来
2、主应用路由切换和子应用路由切换点击浏览器退回没反应
✨问题复现:
官方示例:wujie-micro.github.io/demo-main-v…
大家也可以试一下,先点击主应用中的左侧vite 下的页面切换,然后再点击子应用中中间的页面切换,会发现需要点击两次浏览器的返回才能正常返回,可以看到我录屏下的点击返回前进和退回都没反应,只有多点一次才可以,目前还没找到好的解决办法,如果大家有办法解决可以告诉我。
结语
用了无界这么长时间给我的感觉还是比较好的,子应用保活非常丝滑,开箱即用,子应用基本上不需要更改任何代码直接可以继承到无界之中,这个优点真的是非常棒!不像qiankun 还得写很多适配的代码,当然qiankun 的社区真的比无界强大很多,很多问题你都能找到解决方案,只能说各有优缺点吧,主要看你自己怎么选择了
来源:juejin.cn/post/7444134659719610380