Creating a micro-frontend blackbox with React

Naim Gkamperlo
3 min readMay 22, 2020

--

Blackbox pattern is a pattern developed to solve a lot of issues that usually come up in MFE development.
You can find more here:
https://medium.com/@naimgaberlo/micro-frontend-blackbox-pattern-295c40b681e4

In this post, we are going to make a deep-dive in blackboxes by going through a step by step guide using React and Webpack.

Source can be found at the end of the article. So here we go…

Step 1 - Create a React Typescript app

Steps detailed here:
https://create-react-app.dev/docs/adding-typescript/

Step 2 - Eject React app to create custom webpack build

npm run eject

Step 3 - Create vanilla.tsx

vanilla.tsx is the file which performs the following:

  1. Create a React renderer for vanilla JS
  2. Register basic React’s lifecycle events to window
  3. “Listen” to caller MFE’s ‘openBlackbox’ custom event to render itself on DOM element set in “init” function
import React from "react";import ReactDOM from "react-dom";import App from "./App";// buffer of DOM elements rendering React componentslet nodes: Element[] = [];let hostElement: Element;const reactContentRenderer = {unmountAll: () => {if (nodes.length === 0) {return;}nodes.forEach((node) => ReactDOM.unmountComponentAtNode(node));nodes = [];},unmount: (node: Element) => {ReactDOM.unmountComponentAtNode(node);},init: (targetNode: Element) => {hostElement = targetNode;},render: (props: any, callback: () => void) => {const reactElement = React.createElement(App, props, null);ReactDOM.render(reactElement as any, hostElement, callback);nodes.push(hostElement);return reactElement;},};//register self as window propertywindow["blackbox"] = reactContentRenderer;//and listen to window custom event//which will be invoked via caller MFEwindow.addEventListener("openBlackbox",(e: any) => {const eventDetail = e.detail;console.log("Blackbox open with payload", eventDetail);reactContentRenderer.render(eventDetail, () => {});},false);

Step 4 - Custom webpack build

  • Create webpack.vanilla.config.js (a copy of existing webpack.config.js)
  • Change the webpack.vanilla.config.js entry:
entry: './src/vanilla.tsx'
  • and output:
path: path.resolve(__dirname, '../build') 
filename: 'blackbox.js'
  • remove splitChunks & runtimeChunk in case you need a single file as output

Step 5 - Custom build-vanilla.js

ConfigFactory variable should be changed to point to freshly created webpack.vanilla.config.js

const configFactory = require('../config/webpack.vanilla.config');

Step 6 - Fix tsconfig.json

Add the following compilerOption in tsconfig.json to suppress any array index(by default number is expected)

“suppressImplicitAnyIndexErrors”: true

Step 7 - Add build:vanilla to package.json and run

In package.json add the following in scripts line:

"build:vanilla": "node scripts/build-vanilla.js"

… and run

npm run build:vanilla

Step 8 - Ready to test!

Run the following in terminal:

cd build
serve -s

The above will serve static files produced as output of step 7.

In your browser if you open the url provided by serve’s output , you will see a blank screen.

To invoke your blackbox from the browser’s console run the following two commands in your developer tool’s console:

window["blackbox"].init(document.getElementById("root"));
window.dispatchEvent(new CustomEvent('openBlackbox',{detail:{test:'string'}}));

Result should be the following

Step 9 - Create a custom event to be subscribed by host

In case you want to be ready for next post, blackbox should dispatch its own “finish” event as described in blackbox pattern.
In order to do so , simply add paste the following in “App.tsx”

import React from "react";import "./App.css";function App() {const closeBlackbox = () => {const event = new CustomEvent("blackboxClosed", {detail: { type: "edit" },bubbles: true,});window.dispatchEvent(event);};return (<div className="App"><header className="App-header"><button onClick={closeBlackbox}>Close blackbox</button></header></div>);}export default App;

In our MFE host we will subscribe to this event to listen to updates from our blackbox. More details in next post ;)

Last words

This is it for today!
In the next post we will create a MFE based app to handle our blackbox using single-spa framework!

As promised, source code can be found in the following repo:
https://github.com/ngkamperlo/blackbox

Thanks for reading and happy coding guys!

--

--