This project shows an example of using Webpack 5 Module Federation for Angular 14.2.0
app with injected remote React 18.2.0
module. NGXS state management is used in Angular app, state is shared between Angular app and React module. Angular app was developed based on the example angular11-microfrontends-ngxs
.
Note the use of yarn, this is required to override the webpack version for the angular cli.
For react-user-list
:
- Install packages:
yarn install
- Start:
pnpm run start
(the app uses port 3002)
For angular-profile
:
- Install packages:
yarn install
- Start:
pnpm run start
- Open the shell http://localhost:4201
Ports could be changed in webpack.config.js
files located in react-user-list
and angular-profile
folders.
To run tests in interactive mode, run npm run cypress:debug
from the root directory of the project. It will open Cypress Test Runner and allow to run tests in interactive mode. More info about "How to run tests"
To build app and run test in headless mode, run yarn e2e:ci
. It will build app and run tests for this workspace in headless mode. If tets failed cypress will create cypress
directory in sample root folder with screenshots and videos.
"Best Practices, Rules amd more interesting information here
angular-profile
app maintains the application stateangular-profile
app includes a form for adding a new userreact-user-list
app contains a table for user list visualizing with Remove buttonreact-user-list
app calls a function to remove user from the app state after clicking Remove button- when user is removed from the store, both
angular-profile
app andreact-user-list
app see the changes.
react-user-list
uses ModuleFederationPlugin
to expose ListUserReactComponent
. The plugin is configured in webpack.config.js
(see below).
plugins: [
new ModuleFederationPlugin({
name: 'list_user',
filename: 'remoteEntry.js',
exposes: {
'./ListUserReactComponent': './src/ListUserReactComponent',
},
shared: {
react: {
singleton: true,
requiredVersion: deps.react,
},
'react-dom': {
singleton: true,
requiredVersion: deps['react-dom'],
},
},
}),
],
angular-profile
contains the shell application which is used to load remote Microfrontends using loadRemoteModule
function. Appropriate code from app.module.ts
is listed below.
function initializeApp(): () => void {
return () => {
loadRemoteModule({
remoteEntry: 'http://localhost:3002/remoteEntry.js',
remoteName: 'list_user',
exposedModule: './ListUserReactComponent',
});
};
}
ModuleFederationPlugin
required in the shell app as well. This configuration listed below.
plugins: [
new container.ModuleFederationPlugin({
name: 'profile',
filename: 'remoteEntry.js',
remotes: {
list_user: `list_user@http://localhost:3002/remoteEntry.js`,
},
shared: {
react: {
singleton: true,
requiredVersion: deps.react,
},
'react-dom/client': {
singleton: true,
requiredVersion: deps['react-dom'],
},
},
}),
]
React component is injected into list-user.component.ts
. Here is a component loaded dynamically.
import('list_user/ListUserReactComponent').then(val => {
this.store
.select<IUser[]>(state => state.users.users)
.subscribe(users => {
this.root.render(
React.createElement(val.ListUserReactComponent, {
users,
onClick: this.handleClicked,
}),
);
});
});
Please, pay attention that a file like decl.d.ts
is required into Angular app.
declare module 'list_user/\*';
These references might be usefull in addition to this project in case you are going to implement Angular&React app with Module federation:
- https://github.com/module-federation/module-federation-examples/tree/master/react-in-vue
- https://github.com/module-federation/module-federation-examples/tree/master/angular11-microfrontends-ngxs
- https://thalava.com/how-to-use-react-web-components-in-angular
- https://medium.com/@zacky_14189/embedding-react-components-in-angular-the-easy-way-60f796b68aef