Skip to content

andreievg/plugins-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

plugins-example

React Remote Module Federation Plugins

Summary

This repo includes a simple react front end host and rust back end. Back end serves remote plugin when placed in backend/plugins folder. Front end host will use any remote plugins that are served by backend and in development mode any local plugins that are in frontend/src/plugins folder (local plugins are hot reloadable)

To run backend cargo run from backend folder.

To run front end yarn install && yarn start from frontend folder.

To build and move First plugin to be served by backend yarn install && yarn build && yarn copy from frontend/src/plugins/First folder, similar with Second plugin. You don't need to build plugin for front end to use it in develop mode, and you will only need to yarn install in plugin folder if plugin adds a new dependency (in fact i've noticed that if all plugins are built it takes some time for front end to start up, I haven't been able to figure it out, but if at least one node_modules folder is deleted it's back to being fast)

Type Safe

Each plugin need to export 'default' from plugin.tsx matching Plugins type, plugins in this version are made to bundle together implementations of various plugin interfaces, allowing one plugin to extend many areas of the app

Local Hot Reload vs Remote Module Federation

Hot reload is enabled by loading plugins from frontend/src/plugins folder in development mode using lazy import:

for (const plugin of LOCAL_PLUGINS) {
import(
// Webpack will actually try to load everything in plugins directory
// which causes issues
/* webpackExclude: /node_modules/ */
`./plugins/${plugin.fileName}/src/${plugin.fileName}`
).then((plugin) => addPlugin(plugin.default));
}

And LOGAL_PLUGINS are loaded in in webpack config:

module.exports = (env) => {
LOCAL_PLUGINS: JSON.stringify(localPlugins),

This is different to remotely served built plugins using module federation. Those are loaded by first getting a list of plugins form the server then fetching them individually and binding to the application:

const plugins = (await (await fetch('http://localhost:8080/plugin/list')).json()) as string[];
for (const plugin of plugins) {
loadPlugin(plugin).then(addPlugin);
}

See module federation dynamic remote example for further explanation of how loadPlugin method works.

Plugins are stored in zustand store, which is populated on startup, when they need to be displayed they are loaded via React.lazy:

const ReactComponent = React.lazy(
// Ract.lazy expect component as default export
async () => ({
default: Component,
})
);

Adding new plugins on demand

This repo is meant to shown an example of a pattern for plugins for your a web application. It's hard to know which areas will need to be extendable/pluggable in the future, if a simple pattern is available, it should be straight forward to extend application with a plugin where it's applicable.

This diff shows the changes that are required to add a new plugin inteface and using in extisting plugin

This diff shows the changes to introduce new plugin after copying existing plugin, note you do have to restart webpack to see new plugin, but after it's registered hot reload should work.

Column Plugins

Column plugin exports a StateLoader component which can be used to fetch data for all of the rows (based on the ids and values in normal invoice rows), a zustand state is shared with each column to then get the relevant data for the column field

About

React Remote Module Federation Plugins

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published