How to share UI state in single-spa using RxJs?

≡放荡痞女 提交于 2021-01-07 02:27:34

问题


As per the single-spa official doc, we can share the application's UI state by using RxJs.

Observables / Subjects (RxJs) - one microfrontend emits new values to a stream that can be consumed by any other microfrontend. It exports the observable to all microfrontends from its in-browser module, so that others may import it.

Link: https://single-spa.js.org/docs/recommended-setup/#ui-state

Link: https://single-spa.js.org/docs/faq/#how-can-i-share-application-state-between-applications

I was trying to create an example in React, where I am using single-spa parcel to include my micro-apps in root application. I was trying to share the UI state using RxJs. When I googled it for single-spa RxJs, I didn't find anything. Can anyone provide me a basic example where I will be able to share UI state for below use cases:

  • Sharing the UI state from root app to my micro-apps.
  • Sharing the UI state from micro-apps to root apps.
  • Sharing the UI state between micro-apps.

回答1:


Here is a high level overview on how to approach this:

  • add rxjs as a shared dependency in your import map

      "rxjs": 'https://unpkg.com/@esm-bundle/rxjs/system/rxjs.min.js,
      "rxjs/operators": 'https://unpkg.com/@esm-bundle/rxjs/system/rxjs-operators.min.js,
    
    • consider pinning these to a specific version!
  • create a utility module (create-single-spa makes this easy!) that sets up and exports the observable with data that you need

  • include this utility module in importmap too

  • import and subscribe to observable from the utility module in the apps that need it

    • don't forget to unsubscribe when your apps unmount.
  • celebrate 🎉

I have created single-spa-example-rxjs-shared-state as an example repo that shows how to use an Rxjs utility module with cross-frontend imports.




回答2:


This does the trick In root html js file add the following

Import { Subject, Subscription } from 'https://dev.jspm.io/rxjs@6/_esm2015';
import { filter, map } from 'https://dev.jspm.io/rxjs@6/_esm2015/operators';

export class EventBusService {


  constructor() {this.subject$ = new Subject(); }

  emit(event) {
    this.subject$.next(event);
  }

  on(eventName, action) {
    return this.subject$.pipe(
      filter( (e) => e.name === eventName),
      map( (e) => e["data"])).subscribe(action);
  }
}

var EventBus= new EventBusService()`enter code here`;



System.import('single-spa').then(function (singleSpa) {

    singleSpa.registerApplication(
      'app1',
      function () {
        return System.import('app1');
      },
      function (location) {
        return true;
       // return location.pathname.startsWith('/app1');
      },
      { EventBus: EventBus }
    );

    singleSpa.registerApplication(
      'app2',
      function () {
        return System.import('app2');
      },
      function (location) {
       return true
        // return location.pathname.startsWith('/app2');
      },
      { EventBus: EventBus }
    )

    singleSpa.start();
  })

In component

import { Component,OnInit ,ChangeDetectorRef} from '@angular/core';
import { assetUrl } from 'src/single-spa/asset-url';
import { singleSpaPropsSubject, SingleSpaProps } from 'src/single-spa/single-spa-props';
import { Subscription } from 'rxjs';
@Component({
  selector: 'app1-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit  {

  singleSpaProps: SingleSpaProps;
  subscription: Subscription;
  title = 'app1';
  yoshiUrl = assetUrl("yoshi.png");
  msgFromMicro="";
  titleToPass="";
  constructor(private ChangeDetectorRef:ChangeDetectorRef){

  }
  ngOnInit(): void {
    this.subscription = singleSpaPropsSubject.subscribe(
      props => {
        this.singleSpaProps = props;
        console.log(props);
        this.lookForEvents();
      }
    );
  }
  lookForEvents(){
    this.singleSpaProps['EventBus'].on('msgFrmMicro2',(data)=>{
      this.msgFromMicro=data;
      this.ChangeDetectorRef.detectChanges();
    });
  }
  sendMsg(){
   // alert(this.titleToPass);
   debugger;
   this.singleSpaProps['EventBus'].emit({name:'msgFrmMicro1',data:this.titleToPass});
  }
  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

Take look at the following repo, handled the same scenario by passing observable ref to micro apps through customprops of single spa

https://github.com/SENTHILnew/micro_spa_intercom



来源:https://stackoverflow.com/questions/61500732/how-to-share-ui-state-in-single-spa-using-rxjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!