This article explores the technical implementation of injecting React and Vue remote modules into an Angular shell app using Webpack 5's ModuleFederationPlugin.
Consider a scenario where multiple applications share common components, such as a PROFILE page and a SETTINGS page. Micro-frontends offer compelling advantages in such cases:
Now, let's dive into the technical implementation of using Module Federation to achieve these benefits.
The React "Profile" module contains a simple form where users can edit their name and email. The implementation is straightforward, but it's worth noting that the bootstrap.js file is mandatory due to a bug.
To run the Profile module, navigate to the app folder and execute the following commands:
You can access the form at http://localhost:3001.
In the webpack.config.js
file, the ModuleFederationPlugin settings for the React "Profile" module are as follows:
In this context, the ReactProfileComponent
was made available for external use, and the React libraries were shared. It's important to highlight that any imported code, including elements like CSS styles (profile-style.css
in our example), will be packaged within the exposes module alongside the ReactProfileComponent.tsx
.
The Vue "Settings" module is created to run as an isolated element within the shadow DOM to avoid conflicts between React and Vue in the Angular shell app.
To run the Vue Settings module, navigate to the app folder and execute the following commands:
You can access the module at http://localhost:3002.
In the webpack.config.js
file for the Vue Settings component, the ModuleFederationPlugin settings are as follows:
The configuration ensures that the Vue module can be used within the Angular shell app.
NOTE: To mitigate potential conflicts between React and Vue in the Angular shell app, Vue 3 introduces the use of defineCustomElement
. This feature enables the creation of Vue components as self-contained elements within the shadow DOM.
In the Angular shell application, we'll integrate the React "Profile" module and Vue "Settings" module as remote components.
The timing of when these remote components should be loaded into the Angular shell app varies based on the specific app's needs. In our scenario, we want the React and Vue components to be visible on the homepage of the Angular shell app, so we run the LoadRemoteModule
methods as part of the app's initialization process.
In the app.module.ts
file, the initialization process is defined:
Webpack config settings in webpack.config.ts
for the Angular shell define remotes and shared React libraries, allowing the shell to be a federated module
Additionally, to prevent CORS errors, the Webpack devServer is configured with headers to allow access from any origin by setting "Access-Control-Allow-Origin": "*"
.
For customizing the Angular application, it's necessary to update the angular.json
file to utilize a custom Webpack configuration instead of the default setup.
The required modifications are as follows:
Next, we'll focus on injecting the React component into the Angular shell. To achieve this, a profile-user.component.ts
container has been created to integrate the React component. The ProfileReactComponent is loaded asynchronously within the ngAfterViewInit
lifecycle hook. Additionally, a decl.d.ts
file has been introduced to inform Angular that "profile_user"
is a valid import directory.
Here's the code from `angular-shell/src/app/profile-user/profile-user.component.ts``:
The React Profile component interacts with the Angular shell through the onClick
function. This allows the Angular shell app to update user data when changes are made to the name and email in the React component.
Similarly, the Vue Settings component is injected into the settings.component.ts
wrapper. The approach closely resembles that of the React Profile component. Here's the code from angular-shell/src/app/settings/settings.component.ts
:
To run the Angular shell app, please take note of using yarn
. This is necessary to override the webpack version for the Angular CLI. In the angular-shell
folder, execute the following commands:
yarn
as the package manager:The app can be accessed via http://localhost:4201.