Skip to content

微前端架构下,子应用重复注册 composition-api 插件失败,导致插件提供的响应式 API 不可用 #876

Closed
@liyongning

Description

@liyongning
  • 微前端架构(主应用 A、子应用 B、子应用 C)
  • 主应用通过 CDN 引入 vuejs 库
  • 子应用设置 externals vue,此时这套架构下的应用会共用全局对象(window)上的 Vue。

    注意这里不考虑子应用重命名 Vue 的操作,因为不是一个普适的方法,假如我有 100 个子应用,这个操作就很恐怖了

  • 这时,在浏览器打开子应用 B 中的某个页面,这时一切正常,不会有问题
  • 接下来从子应用 B 进入子应用 C,就会出问题了,提示插件已经被注册过了,且子应用 C 中的响应式 API (比如 reactive)调用也会报错,理由如下:
    • 从第一个子应用进入第二个子应用(从 B 进入 C),当在子应用中引用 composition-api 时(import CompositionAPI from '@vue/composition-api),会触发插件中的如下代码:
    if (typeof window !== 'undefined' && window.Vue) {
      window.Vue.use(Plugin)
    }
    • 进而会注册插件,执行插件的 install 方法,从而触发 install 中的检测方法 isVueRegistered,代码如下:
      export function install(Vue: VueConstructor) {
        if (isVueRegistered(Vue)) {
          if (__DEV__) {
            warn(
              '[vue-composition-api] already installed. Vue.use(VueCompositionAPI) should be called only once.'
            )
          }
          return
        }
        // ....
      }
    • 接下来触发 isVueRegistered 方法
      export function isVueRegistered(Vue: VueConstructor) {
        return hasOwn(Vue, PluginInstalledFlag)
      }
    • 因为子应用共用全局对象上的 Vue,所以 isVueRegistered 方法会返回 true
    • 导致 install 方法无法继续往下执行,也就是说子应用 C 中的 vueConstructor 变量是 null
    • image
    • 这时插件虽然在路由进入子应用 B 时已经在 Vue 上注册了,但是当切换到子应用 C 时由于 install 被提前终止,导致下面的 setVueConstructor 没有执行,所以 vueConstructor 变量是 null,代码如下:
      • image
      • image
    • 这时子应用执行响应式 API 时,比如 reactive,执行过程如下:
      • image
      • image
      • image
    • 所以这时候控制台就报错,找不到 Vue

=============================================================================================

针对以上问题,有如下解决办法,可以增强 isVueRegistered 方法的判断能力,比如:
image
目前通过给插件 打补丁 的方式在业务中运行该方案,经验证是可行的,也没发现什么副作用,composition-api 的单元测试也能正常跑过

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions