Skip to content

不同模块的数据通信共享如何做的?

  • 场景:这是一个Monorepo+微前端项目,需要在几个子系统和之间共享关键数据。 然后麻烦的点是,这几个子系统的基座系统,不全是同一个,然后,也不全在这个Monorepo当中。在我来这个项目之前,我mt当时是考虑了这个仓库的体积,以及时间成本,就没有全部迁移过来。

总结一下背景就是:有多个基座

好了背景说完了。现在我有这么几种方案:

  • 基于微前端注入的window全局对象:

    • 会污染全局空间,并且没有响应式
    • 任何地方都能修改,难以追溯和调试
    • 在不同基座的系统中,也不好传递
  • 基于 localStorage / sessionStorage

    • 浏览器天然支持,兼容性好
    • 但是
      • 同步阻塞,无响应式,还有容量限制
  • 基于共享的MobX Store、Zustand等等

    • 只需要主应用发布实例,然后通过webpack5的模块邦联模式进行远程共享即可
      • 这里有一个问题?如何确保远程共享的实例是同一个?

      • 答:使用模块邦联的shared,它会确保只要只有一个实例被加载和执行,即使有不同的基座,也可以。

      • 而且模块邦联模式,可以做到与技术栈、代码仓库位置、甚至部署环境都完全解耦。

  • 最终方案:因为其中几个包特别大,再多一个包是需要仔细考虑的。其次,这个场景下,要同步的数据并不太多,所以应该遵循怎么简单怎么来的原则。

所以还是选择了localStorage / sessionStorage,因为它最简单直接。

但是,如果我来设计的话,可以混合CustomEvent封装一个发布订阅模式,然后再要扩展的话,

js
// A lightweight wrapper for localStorage communication
class SharedState {
  set(key, value) {
    const data = JSON.stringify(value);
    localStorage.setItem(key, data);
    // Manually dispatch an event for same-tab communication
    window.dispatchEvent(new CustomEvent('shared-state-change', {
      detail: { key, value }
    }));
  }

  get(key) {
    const data = localStorage.getItem(key);
    return data ? JSON.parse(data) : null;
  }

  // Allow other apps to subscribe to changes
  subscribe(key, callback) {
    const handler = (event) => {
      if (event.detail && event.detail.key === key) {
        callback(event.detail.value);
      }
    };
    window.addEventListener('shared-state-change', handler);
    
    // Return an unsubscribe function
    return () => window.removeEventListener('shared-state-change', handler);
  }
}

// Export a singleton instance
export const sharedState = new SharedState();

即使在业务上落地比较复杂,要考虑很多东西,描述起来也比较简单,前端的工作往往是这样。所以我后面的讲述尽量放在一个具体的场景里面,来显示我的一些方案选择。

本站访客数 人次 本站总访问量