Microfrontend Core Library for React
$ npm install --save @redneckz/microfront-core @redneckz/microfront-core-react
or:
$ yarn add @redneckz/microfront-core @redneckz/microfront-core-react
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { Router } from 'react-router-dom';
import { container, MicroFrontModuleBootstrap } from '@redneckz/microfront-core';
import { Container } from '@redneckz/microfront-core-react';
// Each and every micro frontend should implement async "bootstrap" function
export const bootstrap: MicroFrontModuleBootstrap = async ({ route: rootRoute }) => {
// Global stuff can be lazily loaded here
const { App } = await import('./App');
const { createBrowserHistory } = await import('history');
// Relative to MF root route
const history = createBrowserHistory({ basename: rootRoute });
return {
mount: async mountingRoot => {
render(
<Container instance={container()}>
<Router history={history}>
<App />
</Router>
</Container>,
mountingRoot
);
},
unmount: async mountingRoot => {
unmountComponentAtNode(mountingRoot);
}
};
};
import React, { useCallback } from 'react';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import { useContainer } from '@redneckz/microfront-core-react';
export const Header: React.FC = () => {
// Outside of micro frontend context returns identity function
const container = useContainer();
const onSignUp = useCallback(
container(() => {
// isolation is here
}),
[]
);
return (
<Toolbar>
<Button onClick={onSignUp}>Sign up</Button>
</Toolbar>
);
};
import React from 'react';
import { useMicroFrontParams } from '@redneckz/microfront-core-react';
export const Page: React.FC = () => {
const params = useMicroFrontParams();
return params ? (
<article>This page is rendered as a micro frontend on the route `{params.route}`</article>
) : (
<article>This page is rendered as a regular page</article>
);
};
Parametrize bootstrap: MicroFrontModuleBootstrap<?>
with additional props type.
Export such types as a library to simplify integration with host container.
import type { HeaderProps } from './Header';
export const bootstrap: MicroFrontModuleBootstrap<HeaderProps> = async ({ title }) => {
const { Header } = await import('./Header');
return {
mount: async mountingRoot => {
...
},
unmount: async mountingRoot => {
...
}
};
}
Integrate micro frontend with host container and pass in additional params:
import React from 'react';
import { register } from '@redneckz/microfront-core';
import { MicroFrontContainer } from '@redneckz/microfront-core-react';
import { Layout } from './Layout';
/**
* It would be nice to have the latest typings of micro frontends
* on host container to fix integration problems ASAP at compile time.
* But keep in mind that host <-> microfront contract should be as simple as possible.
*/
import type { HeaderProps } from '@typings-scope/typings-library/Header';
const bootstrapHeader = register<HeaderProps>(
'foo', // remote module name according to Module Federation config
() => import('foo/Header') // remote module
);
...
export const App: React.FC = () => (
<Layout
header={
/* Typings are correctly seeped from "bootstrapHeader" to "MicroFrontContainer" */
<MicroFrontContainer bootstrap={bootstrapHeader} title="Micro Frontends">
{mountingRootRef => <div ref={mountingRootRef}>Loading...</div>}
</MicroFrontContainer>
}
>
...
</Layout>
);