Use Cases for UiSdlFederatedComponent
The UiSdlFederatedComponent component allows a third-party library or an application to be embedded inside your C3 AI UI application. Using UiSdlFederatedComponent component is consistent with other component configurations. You can extend and build the C3 AI application as a federated application composed of multiple federated modules instead of completely rewriting applications to fit your specific needs.
The walkthrough helps you do the following:
- Build Micro Frontends.
- Leverage existing investments you already have in place.
To learn more, see Micro front end with module federation in webpack.
To integrate a third-party application
Requirements for the third-party application:
Bundle using the
Webpackplugin ModuleFederationPlugin.Expose the function named
renderAppInsideDivthat allowsUiSdlFederatedComponentto pass it a React reference, which has adivattached to it. Any contexts required by the third-party application must be rendered through this function. The following codeblock is an example of the described approach:JavaScript// RemoteBootstrap.jsx import App from './App'; import i18n from './lib/i18n'; import store from './redux/store'; import ErrorBoundary from './components/ErrorBoundary'; const RemoteBootstrap = () => { return ( <React.StrictMode> <I18nextProvider i18n={i18n}> <Suspense fallback={<></>}> <Provider store={store}> <ErrorBoundary> <DndProvider> <App /> </DndProvider> </ErrorBoundary> </Provider> </Suspense> </I18nextProvider> </React.StrictMode> ); } // Function that takes a React ref, which has a `div` attached to it at `ref.current` const renderAppInsideDiv = (ref) => { ReactDOM.render(<RemoteBootstrap />, ref.current) } export default RemoteBootstrap; export { renderAppInsideDiv };- This allows the third-party application to render the application inside the passed
divand separate the (potentially) different versions of React, and avoid theYou might have more than one copy of React in the same apperror described here.
- This allows the third-party application to render the application inside the passed
Expose the previous (
RemoteBootstrap) component in itsModuleFederationPluginconfiguration. The following codeblock is an example of the described approach:JavaScript// webpack.config.js ... new ModuleFederationPlugin({ name: 'stories', filename: 'remoteEntry.js', remotes: {}, exposes: { './StoriesApp': './src/RemoteBootstrap', }, ...
Routes in third-party applications
If the application uses internal URL paths for routes, the third-party application's routes can have issues. This is because the parent C3 AI UI application receives the route first which means a route missing error can occur when looking for the other routes.
For example, if the third-party application has a route for /users but this route does not match the UI application’s routes, a “route missing” error would be thrown in the UI application. You can provide a configuration that allows the third-party application to use hash-based internal routing, so it will not conflict with the parent C3 AI UI application. For example, now the route would be #users so the C3 AI UI application route would still be valid, while allowing the third-party application to perform its internal routing.
Configure UiSdlFederatedComponent
UiSdlFederatedComponent is configured in the same way other components are configured. The component exposes three required properties. See the following codeblock to see the three exposed properties.
/**
* Provides an interface to render a Webpack federated module within an SDL application.
*/
type UiSdlFederatedComponent mixes UiSdlComponent<UiSdlNoData> {
/**
* The path to the remoteEntry.js file. Should be relative to the server root; this cannot be a full
* https url, as that could cause CORS issues.
* Example: if the remoteEntry.js file was at [package]/ui/content/remoteEntry.js, the remoteEntryUrl
* would be './remoteEntry.js'
*/
remoteEntryUrl: !string
/**
* The name of the component to be imported. This should match what is in the "exposed" field in the federated
* module's configuration.
*/
componentName: !string
/**
* The name of the federated module. This should match what is in the "name" field in the federated module's
* configuration.
*/
federatedModuleName: !string
/**
* Optional: if a custom renderer is desired, the name of the type should be added as a
* configuration option.
* TODO: UI-12676
*
* rendererName: string
*/
}A typical component JSON configuration can look like the following codeblock:
{
"type" : "UiSdlConnected<UiSdlFederatedComponent>",
"component" : {
"remoteEntryUrl": "remoteEntry.js",
"componentName": "./MyExposedComponent",
"federatedModuleName": "testModule"
}
}