异步加载组件在qiankun和vite的深坑

869 阅读2分钟

背景

我希望将一些业务关联性不强的、通用性比较高的页面通过插件的形式去开发,主应用通过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",
 });

理想很丰满

我整体的思路是这么设计的:

  1. 主应用通过sdk加载vue、vue-router等,这样做到和插件保持一致

image.png 2. 插件通过rollupOptions来过滤vue、vue-router,使用全局的

image.png

遇到的坑

  1. 由于的主应用是一个qiankun的子应用,qiankun默认不允许子应用去加载sdk 如果加载了 也会给你注释掉

image.png 网上搜了一下,有个解决方案。

image.png 哔了狗的,整个只能一次性注册的start去用,我的qiankun主应用使用的是loadMicroApp局部注册,查了一堆资料,问了半天gpd,都是无解

  1. 尝试把vue,vue-router打包进插件里面去

我想着,不让用就不让用了呗。我把vue打包进插件了,无非就是包大了点呗。于是我把rollupOptions里的external给注释掉,然后打了个包。。

结果发下,能用是能用了,结果我的element-plus、还有我自己封装的ui组件库全都不能用了。。。。

这尼玛是为什么呢?不是说好的注册到createApp的实例上的吗?(这点到现在还没去看,估计还是放到了Vue原型上去记录注册的全局组件)。

解决方案

摆在我面前的就是两条路:要么不让qiankun去劫持注释我的sdk,要么让插件能够用全局注册的组件库。从吃完午饭研究到快下班,想到了插件去局部注册?使用script懒加载sdk,都没有走通。。

忽然我想到了sdk为啥能被加载,无非就是挂到了window上面去了呗。

image.png 既然他挂到window上了,我为什么不能自己去挂??我不但能自己挂,我tm还能自己起名字。 于是乎,我悟了

image.png 然后插件端改下名字

image.png 结果再试一下,成了!!!

image.png

总结

import加载依赖如果指定了external,他就会去window下找。如果你使用了微前端,由于主应用的安全机制,你是不能通过sdk来获取window.vue这种全局对象。我们可以通过子应用自己去申明window.vue的方式让插件去使用

至于为什么app.use()注册的全局组件,在不同vue对象上不能通用的问题 我还没搞明白 准备有空再看下