-
Epic
-
Resolution: Unresolved
-
Undefined
-
None
-
None
-
Dynamic plugins should support context and listeners mount points
-
False
-
-
False
-
To Do
-
QE Needed, Docs Needed, TE Needed, Customer Facing, PX Needed
-
-
EPIC Goal
Plugins should have the option to define a React "context" or "listener" (maybe we find another name for this?) component.
We should allow plugins to add two new mount point (types):
1. An application context:
dynamicPlugins: frontend: my-plugin: mountPoints: - mountPoint: application/context-provider importName: MyContextProvider
that wraps the complete application tree like this:
// packages/app/src/App.tsx export default app.createRoot( <> <AppRouter> <Root> <MyContextProvider> {routes} </MyContextProvider> </Root> </AppRouter> </>, );
This is useful and required for global states and integrations like analytics, chat integrations, etc.
2. A application listener:
dynamicPlugins: frontend: my-plugin: mountPoints: - mountPoint: application/listener importName: MyListener
that loads a component on the side of the application:
// packages/app/src/App.tsx export default app.createRoot( <> <AppRouter> <MyListener /> <Root>{routes}</Root> </AppRouter> </>, );
This is useful for all global loaders/handlers/listeners that must not be part of the react tree. It reduces the risk of failures.
We might need wrap both cases in ErrorBoundaries to ensure that issues in that components doesn't break the complete application.
Background/Feature Origin
RHDH showcase supports different kind of mount points, like routes, home page cards, and some more for catalog entity pages. See https://github.com/janus-idp/backstage-showcase/blob/main/showcase-docs/dynamic-plugins.md
But some plugins might need to mount a component on a root level of the React application like the home plugin. See VisitListener on https://github.com/backstage/backstage/tree/master/plugins/home
Code example:
// packages/app/src/App.tsx import { VisitListener } from '@backstage/plugin-home'; // ... export default app.createRoot( <> <AlertDisplay /> <OAuthRequestDialog /> <AppRouter> <VisitListener /> <Root>{routes}</Root> </AppRouter> </>, );
Why is this important?
Allow plugin authors write plugins that requires such a global state.
For example: The dynamic home page plugin requires a global listener that saves all visited pages to the database.
Dependencies (internal and external)
None
Acceptance Criteria
- New mount points are supported
- Updated https://github.com/janus-idp/backstage-showcase/blob/main/showcase-docs/dynamic-plugins.md
Release Enablement/Demo - Provide necessary release enablement details
and documents
DEV - Upstream code and tests merged: <link to meaningful PR or GitHub
Issue>
DEV - Upstream documentation merged: <link to meaningful PR or GitHub
Issue>
DEV - Downstream build attached to advisory: <link to errata>
QE - Test plans in Playwright: <link or reference to playwright>
QE - Automated tests merged: <link or reference to automated tests>
DOC - Downstream documentation merged: <link to meaningful PR>