Skip to content

Commit

Permalink
docs: better define discovery opportunities
Browse files Browse the repository at this point in the history
  • Loading branch information
Adolfo R. Brandes authored and arbrandes committed Nov 10, 2022
1 parent 8fa9176 commit 48a7cb3
Showing 1 changed file with 58 additions and 21 deletions.
79 changes: 58 additions & 21 deletions oeps/architectural-decisions/oep-XXXX-micro-frontend-domains.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ OEP-XXXX: Micro-frontend Domains
* - Authors
- Adolfo R. Brandes <[email protected]>
* - Arbiter
- TBD
- Adam Stankiewicz <[email protected]>
* - Status
- Draft
* - Type
Expand All @@ -29,20 +29,28 @@ OEP-XXXX: Micro-frontend Domains
- TBD


***********
Terminology
***********

* *MFE*: a micro-frontend
* *SPA*: single-page application
* *DDD*: domain-driven development

********
Abstract
********

The decision to gradually implement a micro-frontend architecture for Open edX was a largely successful attempt at avoiding some limitations of the monolithic ``edx-platform`` codebase. In particular, it allowed the project to integrate more and better features by leveraging newer frontend technology, all much faster than would have been possible otherwise. At the same time, because features encapsulated in micro-frontends (henceforth, "MFEs") are very loosely coupled to each other, this architecture eliminates most integration bottlenecks, allowing individual teams working on any given feature to not be a lot more *productive*.
The decision to gradually implement a micro-frontend architecture for Open edX was a largely successful attempt at avoiding some limitations of the monolithic ``edx-platform`` codebase. In particular, it allowed the project to integrate more and better features by leveraging newer frontend technology, all much faster than would've been possible otherwise. At the same time, because features encapsulated in MFEs are very loosely coupled to each other, this architecture eliminates most integration bottlenecks, allowing individual teams working on any given feature to be a lot more *productive*.

However, roughly 3 years into this gradual re-platforming, several drawbacks to the chosen implentation of complete single-page app ("SPA") independence have been identified. This OEP proposes a middle-ground based on Domain Driven Development ("DDD") and current industry best-practices, where a minor increase in integration costs is traded for large potential gains in user experience, customizability, ease of deployment, and in certain cases, even development efficiency.
However, roughly 3 years into this gradual re-platforming, several drawbacks to the choice of complete SPA independence have been identified. This OEP proposes a middle-ground based on DDD and other industry best-practices, where a minor increase in integration costs is traded for large gains in user experience, customizability, ease of deployment, and development efficiency.


**********
Motivation
**********

When moving to micro-frontends, a (now known to be) uncommon choice was made: to have *completely* independent SPAs, each with their separate deployment, endpoint, and different technology stack. While the goal of developing platform features more efficiently was achieved, the price to pay was not insignificant. Here are some critical issues that the new architecture introduced:
When moving to MFEs, a (now known to be) uncommon choice was made: to have *completely* independent SPAs, each with a separate deployment, URL, and technology stack. While the goal of developing platform features more efficiently was achieved, the price to pay was significant. Here are some critical issues that the new architecture introduced:

* Inconsistency between MFEs and the legacy codebase

Expand All @@ -66,6 +74,7 @@ When moving to micro-frontends, a (now known to be) uncommon choice was made: to

* Inefficient use of network bandwidth

* Inability to route (e.g., with react-router) between MFEs, necessitating a full refresh each time;
* Dependencies have to be downloaded multiple times by the browser.

* Inconsistent documentation
Expand All @@ -75,7 +84,7 @@ When moving to micro-frontends, a (now known to be) uncommon choice was made: to

* Inconsistency in deprecation efforts

* The gradual replacement of features goes contrary to the Principle of Least Surprise: why did a feature disappear between releases?
* The gradual replacement of features often goes contrary to the Principle of Least Surprise: features are modified or removed with little to no warning between releases.

Some of these are a natural consequence of abandoning server-side rendering; in particular, the authors do not suggest it will ever be possible for an operator to override *anything* on a page without forking the codebase, as was possible with Comprehensive Theming. However, it seems all of the listed problems can at least be ameliorated - if not completely resolved - by implementing a combination of industry best-practices that have risen to maturity in the past couple of years, all of which introduce foreseeable costs that are clearly outweighed by their advantages.

Expand All @@ -86,7 +95,7 @@ It is thus a good time to consider these practices - specified below - weighing
Specification
*************

This OEP proposes a middle-ground between a monolithic codebase and full MFE independence based on the existing industry-accepted concept of Domain Driven Development. The Open edX frontend will be split into formal top-level domains, including but not limited to the LMS and Studio, each of which will be implemented as a Container SPA that, in turn, will render multiple partly-independent MFEs effectively as components. The latter will be re-engineered to conform to the hosting domain's interfaces.
We propose a compromise between the monolithic codebase and full MFE independence based on Domain Driven Development: the Open edX frontend will be split into formal top-level domains, including but not limited to LMS and CMS, each of which will be implemented as a Container SPA. The container, in turn, will render multiple partly-independent MFEs as sub-components. The latter will be re-engineered to conform to the hosting domain's interfaces.

This is to be a full re-platforming, to be undertaken as a single long-term project prior to release. It is in opposition to the currently in-progress gradual conversion of single pages to fully independent MFEs that can be linked to from the pre-existing monolithic framework; the opposite, injecting legacy pages into a domain SPA as components, would be unjustifiable. The difficulty of working with the legacy codebase is the main reason why it was decided to move to MFEs in the first place!

Expand All @@ -98,40 +107,65 @@ As this OEP is developed, we will further investigate:
#. Domain SPAs and their interfaces
#. Shared dependencies
#. MFEs as components
#. ...

TODO:
Discovery
---------

* What is the relationship of this project to the Modular Learning effort? They're both long-term projects, but is there anything else that could be coordinated between them? Maybe this project should only target the modular codebase, and ignore ``edx-platform`` entirely? (Are the APIs between the two even the same?)
* Are there any further top-level architectural elements to consider?
* What is the relationship of this project to the Modular Learning effort?

* Both are long-term projects, but beyond that, is there anything else that could be coordinated between them?
* Should this project target the modular codebase exclusively, ignoring ``edx-platform``? (Relevant if the APIs are incompatible between them.)

Integration strategy
====================

At time of writing there appear to be three commonly recommended strategies for integration of MFEs into container apps:
To be defined.

Discovery
---------

At time of writing these appear to commonly recommended strategies for integration of MFEs into modular container apps:

* `Run-time integration via JavaScript <https://martinfowler.com/articles/micro-frontends.html#Run-timeIntegrationViaJavascript>`_
* `Run-time integration via Web Components <https://martinfowler.com/articles/micro-frontends.html#Run-timeIntegrationViaWebComponents>`_
* `Webpack Module Federation <https://webpack.js.org/concepts/module-federation/>`_
* `single-spa <https://single-spa.js.org/>`_
* `Piral <https://github.com/smapiot/piral>`_

TODO:
With these in mind:

* Which alternative is easier to understand and implement?
* What are the drawbacks to each, in particular as compared to the other, but also with regards to existing MFE characteristics (which one is better suited for React)? Is there anything that would be much harder to do with one (or both) of them?
* Is Webpack Module Federation mature enough, yet?
* Choose between these, or suggest another, better alternative.
* What are the pros and cons of each integration option, in particular in terms of:

* Cost of conversion: how easy is it to convert existing MFEs to the new paradigm?
* Cost of integration: compare the level of MFE independence.
* Hosting of build artifacts: is it possible to host build artifacts separately on object storage or CDN?
* Lazy loading: is it possible to load MFEs and other components lazily?
* Efficiency of development: consider the level of boiler-plate code.
* User impact: compare the benefits and losses from the point of view of the browser.
* Maturity: how reliable is the codebase? Is it maintained actively? Can it be relied upon to exist in 5 years?
* Project health: is the project active (measure commit activity)? How active is the community?

* Recommend a single choice between the integration options, or suggest another, better alternative.

Domain SPAs and their interfaces
================================

TODO:
To be defined.

Discovery
---------

* What does each initial domain SPA look like with no MFEs? What goes into the containing app (header? footer?), what goes into MFEs?
* What UX elements should go into the domain's containing app? The header? Footer?
* Define further container SPA and interface characteristics.

Shared dependencies
===================

TODO:
To be defined.

Discovery
---------

* What dependencies should be shared between all MFEs? (React, Redux, ...?)
* Should we use lazy loading, and if so, how?
Expand All @@ -140,7 +174,10 @@ TODO:
MFEs as components
==================

TODO:
To be defined.

Discovery
---------

* Define how an MFE will connect to the containing SPA's interfaces.
* Can an MFE be used across domains?
Expand All @@ -150,14 +187,14 @@ TODO:
Reference Implementation
************************

TODO
To be defined.


*********************
Rejected Alternatives
*********************

TODO
To be defined.


**************
Expand Down

0 comments on commit 48a7cb3

Please sign in to comment.