Wk-notes-03-09-micro-frontend-bootstrapper

Micro-front-end-bootstrapper

html container/anchor structure

<div data-widget-type="WIDGET_TYPE">
  <script type="widget">
  {
      "type": "json",
      "generateFrom": "CMS(aem)",
      "purpose": "widget-config-for-feature-and-globals",
      "scope": "per-widget-container"
  }
  <script/>
<div/>
<script src="PATH/TO/BUNDLE/app.js"/>

It is supposed to be self contained and is possibly able to be mounted several time on on page.

bundle/app.js

Idea: register as entry function, Widget as widget base class

register

register = (widgetType: string, widget: Widget) => {
    // widgetType as 'flight-search', 'email-subscription'
    // where we assume one widget type can be mounted several times on one page
    
    // Load config from html
    getConfiguration = (anchorContainer) => {}
    
    // Get the instance from container
    getWidgetInstance = (anchorContainer) => {}
    
    // Render widget on html
    mountWidget = (anchorContainer) => {
        widget = new Widget(id, anchorContainer, configuration);
    }
    
    // Update widget on html
    updateWidget = (anchorContainer, props) => {}
    
    // Update widget on html
    unmountWidget = (anchorContainer) => {}
    
    // render All anchorContainers (potentially multiple)
    renderAll = () => {}
    
    document.addEventListener('DOMContentLoaded', renderAll);
    document.addEventListener('load', renderAll);
}

Widget

class Widget {
    constructor(id, anchorContainer, config){}
    
    // Called on rendering the individual widget
    render(p){
        // - React
        // return <App p={p}/>
        // - Vue ?
        // return null;
        // - Angular ?
        // return null;
    }
    
    // Defines how to mount the widget to the DOM
    renderer() {
        // - React
        // return ReactDOM.render(this.render(this.props), this.node);
        // - Vue
        // new Vue({el: this.node});
        // - Angular
        // platformBrowserDynamic().bootstrapModule(AppModule);
    }
    
    update(props) {
      this.props = props;
      // - Redux
      // this.store.dispatch();
    }
    
    unmount() {
      // - React
      // ReactDOM.unmountComponentAtNode(this.node);
    }
}

A base AppShell for bootstrapping, updating, and unmount.

Thoughts

  • Check requirement, if the bootstrapper needs to support multiple mount for save widget, ideally yes

  • To share a bootstrapper

    • either make a monorepo with all the widgets referencing to single bootstrapper, and bundle it with same vendor bundle (code-split and cache)

    • or make a provider(widget-provider) and reference it to all the package as dependencies and use the provider as the single entry point of bundles

  • We do not actually need a render() as react does, it mixes react behavior with micro-frontend contracts

Last updated