Note |
---|
Any up-to-date implementation details can now be found in the README. |
1. Add @edx/frontend-plugin-framework
as a dependency
...
2. Micro-frontend configuration document (JS)
Micro-frontends that would like to use the plugin framework need to be configured via a JavaScript configuration document, and to include a new pluginSlots config.
Code Block | ||
---|---|---|
| ||
const config = { // other existing configuration plugins: { sidebar: { keepDefault: false, // bool to keep default host content plugins: [ { url: 'https://plugin.app/plugin1', type: IFRAME_PLUGIN, } ] } } } |
3. Host Micro-frontend (JSX)
Hosts must define PluginSlot components in areas of the UI where they intend to accept extensions. The host MFE, and thus the owners of the host MFE, are responsible for deciding where it’s acceptable to mount a plugin. They also decide the dimensions, responsiveness/scrolling policy, and whether the slot supports passing any additional data to the plugin as part of its contract.
Code Block | ||
---|---|---|
| ||
<HostApp> <Route path="/page1"> <SomeHostContent /> <PluginSlot id="sidebar" className="d-flex flex-column" pluginProps={{ className: 'flex-grow-1', title: 'example plugins', }} style={{ height: 700, }} > <DefaultSlotContent /> // removed if keepDefault is false </PluginSlot> </Route> <Route path="/page2"> <OtherRouteContent /> </Route> </HostApp> |
4. Plugin Micro-frontend (JSX) and Fallback Behavior
The plugin MFE is no different than any other MFE except that it defines a Plugin component as a child of a route. This component is responsible for communicating (via postMessage) with the host page and resizing its content to match the dimensions available in the host’s PluginSlot.
It’s notoriously difficult to know in the host application when an iframe has failed to load. Because of security sandboxing, the host isn’t allowed to know the HTTP status of the request or to inspect what was loaded, so we have to rely on waiting for a postMessage event from within the iframe to know it has successfully loaded
Code Block | ||
---|---|---|
| ||
<PluginApp><MyMFE> <Route path="/plugin1mainContent"> <Plugin fallbackComponent={<Fallback />}> <PluginContent <MyMainContent /> </Plugin> </Route> <Route path="/plugin2plugin1"> <Plugin fallbackComponent={<OtherFallback />}> <OtherPluginContent<MyCustomContent /> </Plugin> </Route> </PluginApp>MyMFE> |