背景
我希望将一些业务关联性不强的、通用性比较高的页面通过插件的形式去开发,主应用通过remote-plugin去加载。
整体项目构造
|--packages
|----app
|------src
|--------App.vue
|--------Remote-plugin.vue
|------vite.config.js
|--plugins
|----plugin1
|------src
|--------plugin.vue
|------vite.confg.js
项目整体通过yarn workspace来实现monorepo
本地开发需要将Remote-plugin指向plugin打包后的lib文件下,实现加载
const url = new URL(`../../../plugins/test/lib/index.umd.cjs`,import.meta.url)?.href;
this.loadScript({
url,
libraryName: "test",
});
理想很丰满
我整体的思路是这么设计的:
- 主应用通过sdk加载vue、vue-router等,这样做到和插件保持一致
2. 插件通过rollupOptions来过滤vue、vue-router,使用全局的
遇到的坑
- 由于的主应用是一个qiankun的子应用,qiankun默认不允许子应用去加载sdk 如果加载了 也会给你注释掉
网上搜了一下,有个解决方案。
哔了狗的,整个只能一次性注册的start去用,我的qiankun主应用使用的是loadMicroApp局部注册,查了一堆资料,问了半天gpd,都是无解
- 尝试把vue,vue-router打包进插件里面去
我想着,不让用就不让用了呗。我把vue打包进插件了,无非就是包大了点呗。于是我把rollupOptions里的external给注释掉,然后打了个包。。
结果发下,能用是能用了,结果我的element-plus、还有我自己封装的ui组件库全都不能用了。。。。
这尼玛是为什么呢?不是说好的注册到createApp的实例上的吗?(这点到现在还没去看,估计还是放到了Vue原型上去记录注册的全局组件)。
解决方案
摆在我面前的就是两条路:要么不让qiankun去劫持注释我的sdk,要么让插件能够用全局注册的组件库。从吃完午饭研究到快下班,想到了插件去局部注册?使用script懒加载sdk,都没有走通。。
忽然我想到了sdk为啥能被加载,无非就是挂到了window上面去了呗。
既然他挂到window上了,我为什么不能自己去挂??我不但能自己挂,我tm还能自己起名字。
于是乎,我悟了
然后插件端改下名字
结果再试一下,成了!!!
总结
import加载依赖如果指定了external,他就会去window下找。如果你使用了微前端,由于主应用的安全机制,你是不能通过sdk来获取window.vue这种全局对象。我们可以通过子应用自己去申明window.vue的方式让插件去使用
至于为什么app.use()注册的全局组件,在不同vue对象上不能通用的问题 我还没搞明白 准备有空再看下