# Communicate Between Micro Frontends
Recommended Learning
- Tutorial: Create a React Micro Frontend
- Tutorial: Create an Angular Micro Frontend
Entando supports communication between micro frontends using Custom Events (opens new window), an established web standard. In this tutorial, we'll build:
- A React micro frontend that publishes an event
- A React micro frontend that listens to an event
- An Angular micro frontend that publishes an event to a React micro frontend
# Publisher
Create a simple app to publish an event.
npx create-react-app publisher-widget --use-npm
Start the app.
cd publisher-widget
npm start
# Create Custom Event
Next, add event firing logic.
Add a new file publisher-widget/src/PublisherWidgetElement.js.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
const EVENTS = {
greeting: 'greeting',
};
class PublisherWidgetElement extends HTMLElement {
constructor() {
super();
this.onGreet = name => this.publishWidgetEvent(EVENTS.greeting, { name });
}
connectedCallback() {
this.mountPoint = document.createElement('div');
this.appendChild(this.mountPoint);
this.render();
}
publishWidgetEvent(eventId, detail) {
const widgetEvent = new CustomEvent(eventId, { detail });
window.dispatchEvent(widgetEvent);
}
render() {
ReactDOM.render(<App onGreet={this.onGreet} />, this.mountPoint);
}
}
customElements.define('publisher-widget', PublisherWidgetElement);
export default PublisherWidgetElement;
- In the
CustomEventconstructor,detailis the specific name to use in the event payload, as per the DOM specification (opens new window).
# Import Custom Element
Update publisher-widget/src/index.js.
import './index.css';
import './PublisherWidgetElement';
# Test Custom Element
Update publisher-widget/public/index.html, and view it in the browser.
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<publisher-widget />
...
</body>
# Update React App to Dispatch Event
Update publisher-widget/src/App.js.
import React from 'react';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = { name: ''};
}
handleNameChange(value) {
this.setState(prevState => ({
...prevState,
name: value,
}));
}
render() {
const { name } = this.state;
const { onGreet } = this.props;
return (
<div>
<h1>Send a greeting</h1>
<label htmlFor="name">Name</label>
<input id="name" onChange={e => this.handleNameChange(e.target.value)} value={name} />
<button onClick={() => onGreet(name)}>Say hello!</button>
</div>
);
}
}
export default App;
# Test Event Dispatcher
In the JavaScript console of your browser, enter:
window.addEventListener('greeting', (evt) => console.log('Hello', evt.detail.name))
Write something in the text field. Click the "Say hello!" button and take a look at the JS console. It will show the event message.
Congratulations!
You’ve now published a custom event.
# Subscriber
Next, let’s create the subscriber.
npx create-react-app subscriber-widget --use-npm
Start the app.
cd subscriber-widget
npm start
# Add Event Listener
Add a new file subscriber-widget/src/SubscriberWidgetElement.js.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
const EVENTS = {
greeting: 'greeting',
};
class SubscriberWidgetElement extends HTMLElement {
constructor() {
super();
this.name = null;
this.subscribeToWidgetEvent(EVENTS.greeting, (evt) => this.onGreeting(evt.detail.name));
}
connectedCallback() {
this.mountPoint = document.createElement('div');
this.appendChild(this.mountPoint);
this.render();
}
subscribeToWidgetEvent(eventType, eventHandler) {
window.addEventListener(eventType, eventHandler);
}
onGreeting(name) {
this.name = name;
this.render();
}
render() {
ReactDOM.render(<App name={this.name} />, this.mountPoint);
}
}
customElements.define('subscriber-widget', SubscriberWidgetElement);
export default SubscriberWidgetElement;
# Import Custom Element
Update subscriber-widget/src/index.js.
import './index.css';
import './SubscriberWidgetElement';
# Test Micro Frontend
Update subscriber-widget/public/index.html, and view it in the browser.
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<subscriber-widget>
...
</body>
# Display Custom Event
Update subscriber-widget/src/App.js.
import React from 'react';
import './App.css';
function App({ name }) {
return name ? (<h2>Just got a greeting from {name}</h2>)
: (<h2>Waiting for a greeting...</h2>);
}
export default App;
# Test Event Listener
In the JavaScript console of your browser, enter:
const widgetEvent = new CustomEvent('greeting', {
detail: {
name: 'Pippo'
},
});
window.dispatchEvent(widgetEvent);
The custom event should now display in the subscriber-widget.
Congratulations!
You’ve now created a micro frontend that listens to custom events.
# Add Widgets to App Builder
Now let's add the publisher and subscriber micro frontends in Entando.
Note: These are the same steps as the
Create a React Micro Frontendtutorial.
# Create Environment File
# Publisher Widget
Create an
.envfile in the project root for thepublisher-widget.Open the
.envfile, and enter thePUBLIC_URLwhere the micro frontend will be hosted.
Example:
PUBLIC_URL=http://quickstart-entando.192.168.64.34.nip.io/entando-de-app/cmsresources/publisher-widget
Notes
- Replace
quickstart-entando.192.168.64.34.nip.iowith the ingress you use to access Entando from your local browser. /entando-de-app/cmsresources/is your Resource URL.publisher-widgetis the public folder we'll create to host the publisher micro frontend.
# Subscriber Widget
Create an
.envfile in the project root for thesubscriber-widget.Open the
.envfile, and enter thePUBLIC_URLwhere the micro frontend will be hosted.
- Use
subscriber-widgetfor the name of the public folder we'll create to host the subscriber micro frontend.
Example:
PUBLIC_URL=http://quickstart-entando.192.168.64.34.nip.io/entando-de-app/cmsresources/subscriber-widget
# Run npm build
# Publisher Widget
Open a command line, and navigate to the project root of the
publisher-widget.Run build.
npm run build
- Rename the following generated files in the
builddirectory.
| Example of Generated Build File | Rename to | Function |
|---|---|---|
| build/static/js/2.f14073bd.chunk.js | static/js/vendor.js | Third-party libraries |
| build/static/js/runtime-main.8a835b7b.js | static/js/runtime.js | Bootstrapping logic |
| build/static/js/main.4a514a6d.chunk.js | static/js/main.js | App |
| build/static/css/main.5f361e03.chunk.css | static/css/main.css | Stylesheet |
# Subscriber Widget
- Repeat steps 1-3 for the
subscriber-widget.
# Create Public Folder
# Publisher Widget
Navigate to
Entando App Builderin your browser.Go to
Configuration→File Browser→publicClick
Create Folder.Enter
publisher-widget.Click
Save.Click
public→publisher-widget.Create the same folder structure as your generated build directory
publisher-widget/static/csspublisher-widget/static/js
- Upload the files we renamed in the corresponding
jsandcssfolders.
publisher-widget/static/css/main.csspublisher-widget/static/js/main.jspublisher-widget/static/js/runtime.jspublisher-widget/static/js/vendor.js
# Subscriber Widget
- Repeat steps 1-8 for the
subscriber-widget.
# Add Widgets
# Publisher Widget
Go to
Entando App Builderin your browser.Go to
Components→Micro Frontends & Widgetsat the top nav.Click
Add.Enter the following:
Code: publisher_widget→ note: dashes are not allowedTitle: Publisher Widget→ for both English and Italian languagesGroup: Free AccessCustom UI:
<#assign wp=JspTaglibs[ "/aps-core"]>
<link rel="stylesheet" type="text/css" href="<@wp.resourceURL />publisher-widget/static/css/main.css">
<script async src="<@wp.resourceURL />publisher-widget/static/js/runtime.js"></script>
<script async src="<@wp.resourceURL />publisher-widget/static/js/vendor.js"></script>
<script async src="<@wp.resourceURL />publisher-widget/static/js/main.js"></script>
<publisher-widget />
- Click
Save.
# Subscriber Widget
Repeat steps 1-5 for the subscriber widget.
Code: subscriber_widget→ note: dashes are not allowedTitle: Subscriber Widget→ for both English and Italian languagesGroup: Free AccessCustom UI:
<#assign wp=JspTaglibs[ "/aps-core"]>
<link rel="stylesheet" type="text/css" href="<@wp.resourceURL />subscriber-widget/static/css/main.css">
<script async src="<@wp.resourceURL />subscriber-widget/static/js/runtime.js"></script>
<script async src="<@wp.resourceURL />subscriber-widget/static/js/vendor.js"></script>
<script async src="<@wp.resourceURL />subscriber-widget/static/js/main.js"></script>
<subscriber-widget />
# View on a Page
You can setup the widgets on an existing page (such as the Home page) or create your own page using the tutorial here. The following steps assume you'll use the Home page.
Go to
Pages→ManagementFor the
Homepage(folder icon), in theActionscolumn, click the⋮iconClick
Edit.In the
Settingssection, select a Page Template with more than one frame, e.g.1-column:
Page Template: 1 Column
Click
Save and Configure.In the
WIDGETSsidebar on the right:
- Drag
Publisher WidgetandSubscriber WidgetintoFrame 1andFrame 2.
Click
Publish.To view the home page, scroll to the top of the page, and click
Go to Homepage.Enter a greeting in the input field. Press the submit button. The subscriber widget will update with the greeting. Done!
Congratulations!
You can now communicate between micro frontends with Custom Events.
# Angular to React
We can also communicate between micro frontends using different JavaScript frameworks.
In this next example, we’ll create an Angular micro frontend to publish an event, and we'll use the React micro frontend we created in the previous section to receive the event.
# Create Angular Publisher
ng new angular-publisher-widget
Choose the following options:
? Would you like to add Angular routing? No
? Which stylesheet format would you like to use? CSS
Serve the application.
cd angular-publisher-widget
ng serve
# Convert to Custom Element
Next, let's convert our Angular app into a custom element. We'll use Angular elements (opens new window) to transform components into custom elements.
ng add @angular/elements
Replace the contents of angular-publisher-widget/src/app/app.module.ts.
- In this file, we bootstrap the custom element using the
ngDoBootstrapmethod.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ReactiveFormsModule
],
providers: [],
entryComponents: [AppComponent]
})
export class AppModule {
constructor(private injector: Injector) {}
ngDoBootstrap() {
const el = createCustomElement(AppComponent, { injector: this.injector });
customElements.define('angular-publisher-widget', el);
}
}
# Create Custom Event
Replace the contents of angular-publisher-widget/src/app/app.component.ts.
- Here, we're adding code to dispatch the custom event.
import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
const EVENTS = {
greeting: 'greeting',
};
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
greetingForm = new FormGroup({
name: new FormControl(''),
});
publishWidgetEvent(eventId, detail) {
const widgetEvent = new CustomEvent(eventId, { detail });
window.dispatchEvent(widgetEvent);
}
onSubmit() {
const name = this.greetingForm.get('name').value;
this.publishWidgetEvent(EVENTS.greeting, { name });
}
}
# Add HTML Form
Replace the contents of angular-publisher-widget/src/app/app.component.html.
- In the app component html, we're adding a simple form to call our component class
app.component.ts.
<h1>Send a greeting</h1>
<form [formGroup]="greetingForm" (ngSubmit)="onSubmit()">
<label>
Name
<input type="text" formControlName="name">
</label>
<button type="submit">Say hello!</button>
</form>
# View Micro Frontend
Open angular-publisher-widget/src/index.html.
In the <body>, replace <app-root></app-root> with your custom element <angular-publisher-widget />.
<body>
<angular-publisher-widget />
</body>
You can check to see if your micro frontend is working in your browser (e.g., localhost:4200)
# Add to App Builder
Now we're ready to host our micro frontend in Entando.
# Build It
From the project root, type:
ng build --prod --outputHashing=none
This will generate a dist directory.
# Create Public Folder
Navigate to
Entando App Builderin your browser.Click
Configuration→File Browser→public.Create a folder named
angular-publisher-widget.Click
Upload Files.From your generated
distfolder, upload:
main-es2015.jspolyfills-es2015.jsruntime-es2015.js
# Add Widget
Go to
Components > Micro frontends & Widgetsin the Entando App Builder.Click
Addat the lower right.Enter the following:
Code: angular_publisher_widget→ note: dashes are not allowedTitle: Angular Publisher Widget→ for both English and Italian languagesGroup: Free AccessCustom UI:
<#assign wp=JspTaglibs[ "/aps-core"]>
<script async src="<@wp.resourceURL />angular-publisher-widget/main-es2015.js"></script>
<script async src="<@wp.resourceURL />angular-publisher-widget/polyfills-es2015.js"></script>
<script async src="<@wp.resourceURL />angular-publisher-widget/runtime-es2015.js"></script>
<angular-publisher-widget />
- Click
Save.
# View on Homepage
Go to
Pages→ManagementNext to the
Homepage(folder icon), in theActionscolumn, click the⋮iconIn the Search field in right-hand sidebar, enter
Angular Publisher Widget.Drag and drop
Angular Publisher Widgetinto theSample Framein the main body of the page.
Replace
Publisher Widget.
Click
Publish.In the top navigation, on the right, click
Go to Homepage.Enter a greeting in the input field. Press the submit button. The subscriber widget will update with the greeting. Done!
- Note: If you don't see an input field, refresh the page.
Congratulations!
You've now created an Angular micro frontend that can communicate with a React micro frontend.
← Angular Configuration →