Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

For achieving a more flexible system and providing the right basis for future scalability the microfrontends project requires a solid decomposition of its functional domain.

Right now the split is mainly driven technically, e.g., such that everything related to the primary navigation bar should be in a package (microfrontend) dedicated to this subject. However, since the technical domain is distributed in either way (multiple microfrontends may want to place something in the primary navigation bar) it makes rather sense to distribute in terms of the exposed domain. As a result, repositories can be better understood by domain experts and the model of additions / removals scales better.

Current State

Drawing the current architecture could be done in many different ways. Looking at the app shell (the given index.html together with the initial loading script directly referenced in there) we could end up in a diagram like below:

The app shell consists of a loading script that contains SystemJS and the algorithm necessary for loading some initial modules and microfrontends. Furthermore, the translation system is already prepared here.

Some packages (such as react, react-dom, single-spa, but also some openmrs packages) are used also in the loading script - referenced via SystemJS from the import map. The import map is also placed in the index.html from the app shell.

The loading of the microfrontends follows a convention to distinguish between packages (supposed to be lazy loaded) and microfrontends (supposed to be evaluated directly for gathering additional infos such as the activation function).

In terms of repositories we have:

  • openmrs-module-spa (backend module and frontend app shell assets)
  • openmrs-esm-api, openmrs-esm-config, etc. (core modules for cross-cutting concerns)
  • openmrs-esm-login, openmrs-esm-home, ... (core modules for elementary UX elements)
  • openmrs-esm-patient-chart and openmrs-esm-patient-widgets (patient chart page and elements on the page)
  • openmrs-esm-devtools, openmrs-esm-patient-registration, ... (more pages and elements)

Every repository comes its own Webpack configuration, dependencies, and CI/CD pipeline. In terms of isolation / independence this is as good as it gets.

Desired State

While the current state does have some benefits, it also comes with drawbacks. Most notably, some of the modules are actually not exchangeable (at least in practice). For instance, no one would want to replace openmrs-esm-api or openmrs-esm-error-handling in practice. In general, these are just cross-cutting concerns that should be treated like invariants (and are actually already treated as such). As a result it makes sense to combine all these cross cutting concerns in the app shell already.

Since single-spa and other external core packages (e.g., react) are similar in that matter, we could also place these in the app shell, too.

Earlier, we distinguished between the cross-cutting concerns and the elementary UX elements. The latter should either be included in the app shell directly or indirectly via an import map. In any case they are assumed to be always there.

(tbd)

Repositories

One possibility is to utilize a monorepo for combining certain parts:

  • openmrs-module-spa (backend module)
  • openmrs-esm-spa (app shell incl. openmrs-esm-login, openmrs-esm-home, openmrs-esm-primary-navigation, openmrs-esm-styleguide, openmrs-esm-api, openmrs-esm-module-config, maybe also openmrs-esm-devtools)
  • openmrs-esm-patient (patient-registration, patient-chart, decomposed patient-chart-widgets)

The rest remains as single repositories.

(tbd)

Technical Implementation

The foundation that allows a much more flexible and modular system is an extension componentextension slot mechanism. In general, this follows an event listenerevent emitter mechanism - just for components.

(tbd)


  • No labels