微前端-single-spa探索

Author Avatar
Peipei Wong 11月 16, 2019
  • 在其它设备中阅读本文章

这个星期看了single-spa的整体思路和demo,差不多能解答上篇blog的问题了。

1. 如何匹配的路由

sigle-spa在这册子项目的时候,需要指定路由在何种情况下挂载项目,这是不是意味着最好以url的prefix来划分项目更好一些?

import {registerApplication, start} from 'single-spa'
registerApplication(
  // Name of our single-spa application
  'home',
  // Our loading function
  () => import('./src/home/home.app.js'),
  // Our activity function
  () => location.pathname === "" || 
    location.pathname === "/" || 
    location.pathname.startsWith('/home')
);
start()

那么single-spa内部也是通过监听history的变化,进而判断如何挂载项目

// navigation/navigation-event
// ...
// We will trigger an app change for any routing events.
window.addEventListener('hashchange', urlReroute);
window.addEventListener('popstate', urlReroute);

另外single-spa为需要项目之间跳转的a标签,暴露了一个navigateToUrl的方法,我想了一下如果需要在js里面去进行项目之间的跳转,就是用最原始的方法:

window.history.pushState(null, null, url);

2. 多个项目如何通信

single-spa并不提供这个功能,但在github上看到了一个思路:(https://github.com/me-12/single-spa-portal-example)[https://github.com/me-12/single-spa-portal-example]

这个项目只要的思想是:在进行registerApplication的时候,主项目也会为每个子项目挂载一个store,并为每个子项目通过customProps将dispatch传递下去,那么dispatch主要做的就是将每个子项目的每次dispatch都会分发给每个子项目,子项目收到后,各自做自己的事情。

export class GlobalEventDistributor {

    constructor() {
        this.stores = [];
    }

    registerStore(store) {
        this.stores.push(store);
    }

    dispatch(event) {
        this.stores.forEach((s) => s.dispatch(event));
    }
}

3. 打包时,如何将多个子项目相同包合并

这个是不正确的思路,如果每次打包的时候,都需要查找每个子项目的相同包,假如这个“相同”发生变化,那么就意味着主项目中打包出来的公共包需要改变,这是不正确的。微服务必须要尽可能的保持主项目即容器稳定,而不是每次迭代都有更改的可能。所以解决办法是公共包需要手动维护,并且更新的可能性最小。

对于打包这个功能,同样single-spa也不提供这个功能,但官网的文档上提供了三种解决方法:(https://single-spa.js.org/docs/separating-applications)[https://single-spa.js.org/docs/separating-applications]

比较靠谱的是第三个,为此,创建一个manifest文件,该文件在单Spa应用程序的部署过程中进行更新,该manifest控制“ SPA”哪些版本处于“活动”状态。然后根据manifest更改加载哪个javascript文件。

这个可以做到更新单个子项目,而不需要更新其他项目的目的。

暂未实施,这个做为下一步的重点关注。