-
-
Notifications
You must be signed in to change notification settings - Fork 917
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sharing data and state between micro-apps via Redux? #107
Comments
Happy to hear you're considering single-spa or at least looking at building a system that operates similarly. Redux-like state management is not built into single-spa itself, but you can definitely use redux or any other state management system in addition to single-spa. The way you would do this is to have redux in a common dependencies bundle and then have all the child applications import the redux store and use it inside their application. How to share state between single-spa child applications is a common question, and one that I think there still is room for innovation and improvement. At Canopy, we use single-spa in production with 14 child applications, and we have a few techniques for sharing state. We also adopted a convention that we like that simplifies state management. A simplifying conventionAt Canopy, we have only one "main content" child application that is active at any time. There are still multiple applications active at once, but only one of them is rendering the main content that is scrollable. The rest of them (so far) just render fixed position menus. As you're navigating around, the menus might stay in place when the main content applications are switching off. So in the screenshot below, communications-ui is the main content application that is scrollable, and primary-navbar, contact-menu, and workflow-ui are supplementary applications that just are fixed menus. Canopy techniques for sharing stateWe chose not to have a global redux store or state manager at Canopy. What we have preferred is to have each of the child applications manage their own state and be self encapsulated. We were worried that a global store would lead to weird situations where the order in which you navigate around to applications matters. In other words, we wanted to avoid where navigating to App1 and then to App2 would result in a different global state (and bugs) than navigating to App2 and then to App1. Another reason we have liked doing things that way is that we deploy the child applications separately and it is nice to have a blast radius of each deployment. We were worried that having a global state manager would create situations where you couldn't really deploy one of the child applications without worrying about how it interacted with the other apps and the global state. As an alternative, we use the following state sharing techniques:
Anyway, that is how we do it at Canopy. But like I said above, I think this is an area where there could be more innovation. If you guys find a better way to do things, we'd be happy to hear what you've done! |
Hi @joeldenning, I have some questions about your state sharing techniques:
It would be great if you add to the examples repository an example of this technics. Thanks 👍 |
The shared api layer is accessible to all child apps via an // In our case, fetcher is a module registered to SystemJS. But module resolution could also be done by webpack if you're using that.
import {getWithSharedCache} from 'fetcher';
// Get this api object, but share it with all other child applications. Once the user navigates away from user 1's settings page, clear the cache.
// Our specific implementation returns an observable, but it could just as easily return a Promise.
getWithSharedCache('/api/users/1', location => location.href.startsWith('/users/1/settings'))
.subscribe(...)
We do not put the observables on the window, but instead make them exported values from the javascript module for the child application. That way, other child applications can access the observable just with an // child app 1, which exposes an observable
import {Observable} from 'rx'; // The rx library is an implementation of observables
// Single-spa lifecycles, as per normal for a child application
export function bootstrap(props) {...}
export function mount(props) {...}
export function unmount(props) {...}
// Observable for others to import
export const heightOfNavbar = Observable.just(4); // child app 2, which needs the height of the navbar
import {heightOfNavbar} from '../path-to-child-app-1/child-app-1.js';
heightOfNavbar.subscribe(
height => console.log('height', height)
);
My understanding of
I agree! I just created #112 for this. Hopefully we'll find a good way to help others understand their options and how to implement inter-app communication. Contributions accepted, of course. |
Another option would be to use a simple pub/sub event emitter. We have preferred observables because you can control if your subscription includes events that happened in the past before your subscription started (useful when two apps are mounting and you can't guarantee the load order). |
Closing -- feel free to reopen if there are more questions. |
@me-12 @joeldenning Hope https://github.com/arkency/event-bus can do the inter spa communications. I have a doubt on socket connection from app one will be closed if the app is unmounted ? , Hope that is okay ? |
@abelkbil Have a look at my example app which uses redux for communication between apps: https://github.com/me-12/single-spa-portal-example Maybe that's helpful to you. |
@abelkbil It looks like Let me know if I'm misunderstanding or if you have more questions! @me-12's example repo is a good place to look, too! |
@joeldenning Thanks I understand |
You might want to use something like postal.js we have been using this for sometime now in production without issues |
Hi Joel this is nitheesh I am using single spa application concept for my project here i am having 6 independent application all the applications are in Angular now I want to pass the data between two independent application can u please help me here. https://github.com/nchandran030/single-spa-main-application |
Hi @nchandran030 - could you clarify what you need help with? |
Ah I see now that your comment is a duplicate of #552 (comment). I will respond there, instead. |
@nchandran030 Take a look at my repo https://github.com/SENTHILnew/micro_spa_intercom |
Hi Team, Actually I am facing issue while accessing the another application from container app. It gives me CORS issue while loading the application itself. |
CORS issues are resolved in the normal way - adding an Access-Control-Allow-Origin header to the server hosting the files. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors |
it'll be great if you can share an example code for how to use it with single-spa? Thanks |
Hi there @joeldenning,
I came across this project and think it's pretty awesome. It seems to function very closely to how we want to do things at my company. My UI team has been talking more about how we can create a system that can work very much like how this does.
We would, however, require the ability to share data between the loaded micro apps somehow, and would also like to be able to manage the state as well. I may have missed it in the docs, but is this something that is possible currently, or do you know if there is anyone doing anything similar?
We want to be able to develop the different parts of our currently very monolithic application as smaller independent apps that can co-exist and communicate together through some kind of state management (redux) or other kind of interface.
Would love to hear your thoughts on this.
Thanks!
Jared
The text was updated successfully, but these errors were encountered: