Module federation example using React.
create-react-appcurrently uses webpack4. Module federation requires webpack5 so need custom webpack config.- Uses the
webpack.container.ModuleFederationPluginto expose remote customer, property and vehicle components for use in the dashboard. - The
dashboardapp uses components from thecustomer_search,property_searchandvehicle_searchapps.
/dashboard,/customer-search,/property-searchand/vehicle-searchare four separate React projects configured to use webpack module federation./{project}/webpackcontains the webpack configuration. Thecommon-pluginsfile has configuration for theModuleFederationPluginwhich eitherexposescomponents or specifies the relevantremotes./{project}/src/indexdoes not render the app itself, it imports frombootstrapto allow for module federation.
- Within each of the apps,
npm ito install the dependencies andnpm startto run then in development mode. npm buildto build any of the apps, thennpm serveto serve up the build artefacts.customer_searchruns locally on port3001: http://localhost:3001/property_searchruns locally on port3002: http://localhost:3002/vehicle_searchruns locally on port3003: http://localhost:3003/dashboardruns locally on port3000: http://localhost:3000/
Or if you just want to run it with docker:
docker compose upto run everything, same ports as abovedocker compose downto clean up
In any case, it will only work if you run it whilst on the VPN.
- Make use of the singleton option for shared libraries since many cannot handle having multiple instances (react-dom and styled-components for example).
- The remote component interface (i.e. the properties it exposes) should be managed like any other interface contract. It should normally be simple to maintain backward compatibility. A breaking change can be handled by introducing a new component whilst retaining but deprecating the old. Alteratively, deploy the new build to a different location.
- Remote components can have transient state that they can manage internally, but there may also be a need to retain component state beteen mounts / unmounts. For example, the customer search component unmounts when moving to a different page, but we wish to retain both the search criteria and search results so that when we reopen the search page it shows the same information as before. The remote component in this example supports two optional properties:
initialDataandonDataChangethat address this requirement. - Remote components must use namespaces to avoid conflicts. They should have a default namespace but also allow the consumer to override the namespace if required. For example, to support multiple instances of the same component. The namespace can be used to ensure unique html tag attribute identifiers (e.g.
id,name,data-cy, etc.), to ensure unqiue Custom Event names and to avoid css classname conflicts. - Requests to backend APIs will use the origin of the host page - not the origin of the remote component. This may require the backend API to manage a whitelist of allowed origins to support CORS requirements. This approach implies some kind of registration / setup process before using a remote component.
- Remote components will likely need to participate in some form of SSO. In this example, the remote components are provided the relevant JWT access token via their props. Although a real-world example will likely be more complex, providing a token in this manner at least avoids any assumed dependency on the context in which the component is used.