I am working on a system that consists of different backend microservices and a few inter-linked micro-frontend apps (all of them built with ReactJS).
Below is my use case (for brevity, I'm just listing the frontend apps here and leaving out the backend services):
We have the following apps:
Settings, Tickets, Campaigns, Analytics, etc.access_token and a refresh_token. Once these tokens are obtained, the dashboard screen is shownTickets, which must redirect to https://tickets.example.comWhen the redirect happens, I need to be able to pass the authentication information (obtained from https://id.example.com) to the Tickets app (at https://tickets.example.com), so that the tickets app can validate the token when it loads up.
I understand I can redirect the user to https://tickets.example.com?token=<auth_token>&refresh_token=<refresh_token>, but I am not sure if that is a secure way of doing it.
Tried using localStorage, but seems they are also tied up to the host and I was unable to get value from the localStorage of id.example.com from within tickets.example.com
Also, the micro-frontends are deployed separately each with its own subdomain (tickets.example.com, campaigns.example.com, etc.) and I understand that one can use frameworks such as single-spa and Module federation to load them inside a Container app. But this is not what I prefer.
In summary, I would like to know how I can pass bits of information (such as auth tokens, session information, etc.) between any two front-end apps?
Thanks, Sriram
I'm also new to micro frontend. This is how I solve this problem,
This will only work for parent <=> communication, not for the siblings
Let me explain: When I want to pass data from child app to parent app I dispatch action publish to the container(PUBLISH_CONTAINER) and When parent app send data I dispatch an action to subscribe to the container (SUBSCRIBE_CONTAINER) action to redux of the same app.
I have 2 apps, one is the main app(Container), the other is the micro app(MicroApp).
MicroApp App:
webpack.config.js
new ModuleFederationPlugin({
name: 'MicroApp',
filename: 'remoteEntry.js',
exposes: {
'./MicroAppApp': './src/bootstrap',
},
})
pubsub.js
export const pubsub = () => {
let cb;
const publishToContainer = (_cb) => (cb = _cb);
const containerReducer = (state = 0, action) => {
switch (action.type) {
case 'SUBSCRIBE_CONTAINER':
return action.payload; // Do something with the payload
case 'PUBLISH_CONTAINER':
cb && cb(action.payload);
return action.payload; // This is not required
default:
return state;
}
};
const subscribeToContainer = (store) => (state) => {
store.dispatch({
type: 'SUBSCRIBE_CONTAINER',
payload: state,
});
};
return {
containerReducer,
publishToContainer,
subscribeToContainer,
};
};
bootstrap.js
export * from './App';
App.js
const { containerReducer, publishToContainer, subscribeToContainer } = pubsub();
const reducers = () => {
return combineReducers({
containerReducer,
});
};
const store = createStore(reducers());
export const publish = publishToContainer; // this will be used by Container app
export const subscribe = subscribeToContainer(store); // this will be used by Container app
Container App:
webpack.config.js
new ModuleFederationPlugin({
name: 'container',
remotes: {
MicroApp: 'MicroApp@http://localhost:3000/remoteEntry.js',
},
})
App.js
import { subscribe, publish } from 'MicroApp/MicroAppApp';
// Note: publish and subscribe function can be used as redux action similar like MicroApp
const microAppReducer = (state, action) => {
switch (action.type) {
case 'SUBSCRIBE_MICRO_APP':
return action.payload; // Do something with the payload
case 'PUBLISH_MICRO_APP':
publish && publish(action.payload);
// return action.payload; // This is not required
default:
return state;
}
}
subscribe((payload) => store.dispatch({ type: 'SUBSCRIBE_MICRO_APP', payload })); // Micro Front end will send data here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With