This microfrontend setup is configured to have this project acting as the remote.
It is responsible to export the children modules/app which will be loaded at runtime and will be provided with some context e.g. auth, routing.
microfrontend-shell-boilerplate
is a default remote (child) boilerplate meant to be consumed by a host such as microfrontend-shell-boilerplate.
It's important to note the remote has to use a unique name in order to work and not collide with other sibling remotes.
The suggested practice is use such name as:
- Git repository
- Webpack Module Federation configuration
- Module (package.json) name
- CSS wrapper name
The Redux store needs to be isolated and non accessible by the host or by the sibling remotes.
For such reason, the store module (src/store
) exports a custom React Context that is used in the Redux / React-Router Provider components.
import configureStore, { ReduxContext } from './store';
///
///
function ExportableApp({ ...propsFromTheHost, }) {
return (
<Provider store={store} context={ReduxContext}>
<App {...propsFromTheHost} />
</Provider>
);
}
Note While it's not necessary to use Redux in the remote, it's still quite convenient to separate React from the application flow and business logic.
You can choose to adopt a different state manager as long as you keep it isolated and do not allow the children applications to access it.
Due to the nature of the architecture, it's not possible to eliminate the issue of classnames collision.
However, it's important note that the whole microfrontend modules should be wrapped into a single, high-order, unique classname in order to reduce or even eliminate CSS naming collision.
function ExportableModule() {
return (
<div className="uniquely-chosen-remote-name">
<div classNam="header"> ... </div>
<div classNam="body"> ... </div>
<div classNam="footer"> ... </div>
</div>
);
}
And defined the style accordingly in SCSS (CSS can work too)
.uniquely-chosen-remote-name {
.header {
// css rules
}
.body {
// css rules
}
.footer {
// css rules
}
}
The default configuration works when running the host locally, however it's necessary to adjust the settings before deploying online.
In the project root directory you can find the webpack.config.js
configuration file.
Code splitting is automatically enabled when using the ModuleFederationPlugin.
At the webpack.config.js
plugins section, you can find the ModuleFederationPlugin.
The configuration is similar to the following:
plugins: [
new ModuleFederationPlugin({
// Preferable to use a unique name and filename when
// several remotes are being consumed
name: 'app',
library: { type: 'var', name: 'app' },
filename: 'app.js',
// Specify and expose components to be consumed
exposes: {
'./App': './src/Injector',
'./Menu': './src/Menu',
},
shared: [
'react',
'react-dom',
...
],
...
In the expose
configuration, you need to export all the components you expect are going to be use.
Note - export only the modules
Make sure you do not export the bootstrap.tsx
as that is only used locally. When your modules are imported by a host, they do not need to include all the traditional context setup specified in bootstrap.tsx
since the host will be providing that.
Note - set a unique name
Make sure you set the unique name in the following fields:
ModuleFederationPlugin.name
ModuleFederationPlugin.library.name
ModuleFederationPlugin.filename