We want to make it possible to use Bahmni Forms in OpenMRS 3.0 using Microfrontends. For this we don’t want to reinvent the wheel, but rather use as much as possible from the existing implementation.
Right now Bahmni Forms is mostly delivered to the frontend using the
implementer-interface package. This package depends on
bahmni-form-controls, which is the library delivering most of the components.
The architecture thus looks roughly like:
bahmni-form-controls implicitly enforces a number of anti-patterns:
- It performs HTTP calls directly rather than leaving that to the consuming application (i.e., these calls cannot be configured or left to a global handler)
- It comes with global styles to be applied rather than allowing the consuming application to override or set these
- It is delivered in a pre-bundled state, which makes it inefficient for use in arbitrary applications. While some dependencies are rather small (
classnames), others are significant (
- It delivers some components, but misses others, which are crucial (e.g., all the drag and drop handling), effectively resulting in just barely over half of the required components.
- Puts a significant amount of logic in view-driven components instead of distinguishing between controller components and view components.
There are three distinct ways of introducing the
implementer-interface to microfrontends. Variations of the three ways are possible, too:
Fork and pick (Re-assemble
implementer-interfacecomponents / code in a new repository)
Use a generalized output from
implementer-interfaceas actual basis; for the actual
implementer-interfacestandalone application and the microfrontend version
Build the microfrontend version from the same repository
All have their pros and cons. While (1) has the most effort, (3) has the greatest technical challenges.
We would favor a variation of (2) where all controls would be placed in
implementer-interface would still just consume these controls from the library. It would thus reduce the creation of a new Bahmni Forms app to wiring together the components exported by
To be really flexible the styling and some other inner workings would need some adjustments, too.
In total, the previously shown architecture diagram would change to look as follows:
When implementing this architecture the following things would require change:
bahmni-form-controlsshould be delivered in a library state, i.e., not pre-bundled
bahmni-form-controlsshould not require global CSS to be applied and comes with isolated / changeable styling
implementer-interfaceshifts most of its components to
bahmni-form-controls, except application dependent components such as the specific
All components in
bahmni-form-controlsare configurable with respect to their used API functions / calls, i.e., if a component depends on an API call this has to be resolved via a given prop (or alternatively via a context required by
implementer-interface would change slightly internally, however, remain as-is from the outside. In this setup there are multiple locations for new applications such as the microfrontend app:
Within the same repository (
implementer-interfacebecomes a monorepo for all apps)
Within new repositories (but using the same GitHub organization)
Within new repositories (organization independent)
Right now there is no recommendation for the location of these applications. For the microfrontend app specifically we would recommend to choose a location that suits the responsible/maintaining team.
As a result, the architecture for supporting the standalone application together with a new microfrontend app would look as follows:
A discussion resulting in next steps and further insights would be greatly appreciated!