Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Adding ADRs 0002, 0003 and a glossary to OEP-65 #626

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion oeps/architectural-decisions/oep-0065/README
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
OEP-0065 File README

The source for the architecture diagram lives in LucidChart.
The source for the architecture diagrams lives in LucidChart.

It can be found `at this LucidChart URL <https://lucid.app/lucidchart/8c2db108-7c14-4525-8e3a-d2853db68b9e/edit?invitationId=inv_7a61f692-df0b-465b-8ec1-5a18ce4447ca>`_ and should be visible by everyone. If you need to edit the chart, either copy the chart into your own Lucid account or get in touch with the original authors if possible (David Joy - listed on the OEP) for access.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
Frontend App Migrations
#######################

Status
******

Accepted

Summary
*******

This ADR describes a migration path and simplified repository organization for the ``frontend-app-*`` repositories that is compatible with :term:`Module Architecture`: the :term:`Shell` provided by the `frontend-base <https://github.com/openedx/frontend-base>`_ library, :term:`module federation`, and frontend :term:`projects <Project>`.

Please see :doc:`0001-unified-platform-repository` for more information on ``frontend-base``.

Context
*******

OEP-65 proposes adopting webpack :term:`module federation` for Open edX :term:`micro-frontends <Micro-frontend>` (MFEs) as a means to enable :term:`runtime module loading` and :term:`shared dependencies` in the :term:`Open edX frontend`. The OEP lays out a series of changes necessary to enable these capabilities, which it refers to as building a "reference implementation" of runtime module loading and shared dependencies.

This reference implementation is effectively a new underlying architecture for our frontend. This ADR refers to this new architecture as the :term:`module architecture`, as opposed to the historical :term:`micro-frontend architecture` that has existed prior to OEP-65.

As part of this paradigm shift, our ``frontend-app-*`` repositories (MFEs) will need to be migrated to work with `frontend-base <https://github.com/openedx/frontend-base>`_. Of particular note, this will require the repositories to:

* Adopt a new set of build/development CLI helpers
* Use the :term:`shell` to provide the header, footer, and runtime initialization code, amongst other things.
* Organize their code into loosely-coupled top-level components, which are called :term:`application modules <Application Module>`.

As we adopt ``frontend-base``, the libraries it replaces will undergo their own deprecation processes, which will need to coordinate with the migration of micro-frontends included in Open edX releases. After that deprecation, the micro-frontend architecture will cease to be supported.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
As we adopt ``frontend-base``, the libraries it replaces will undergo their own deprecation processes, which will need to coordinate with the migration of micro-frontends included in Open edX releases. After that deprecation, the micro-frontend architecture will cease to be supported.
As we adopt ``frontend-base``, the libraries it replaces will undergo their own deprecation processes, which we'll need to coordinate with the migration of micro-frontends included in Open edX releases. After that deprecation, the micro-frontend architecture will cease to be supported.


Decision
********

Each of our ``frontend-app-*`` repositories will migrate from being an independent "micro-frontend application" to being a library of modules that can be loaded into a common :term:`Shell`, deployed as a :term:`Site`. These are called :term:`application module libraries <Application Module Library>`. We will document the migration process in detail. At a high level, this will involve the following changes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I understand why "Application Module Library" (each former MFE will in theory be able to export multiple modules, making it a library), but I have to ask: would trimming it to "Application Module" also work? It would be easier to remember, pronounce, etc.

Also, if we make the new name too difficult (however accurate), people will just fall back to calling them MFEs. (Which people probably will anyway. 🤷)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm going to drop the word "Application" from it so that it's just 'module library'. I think we should consider, at some point, whether these repos get renamed to be prefixed with frontend-library- or something; I'm not prepared to bite off a real suggestion there yet. :)


New Deployment Methods
======================

The application module libraries will be buildable in several different ways.

* Built as :term:`imported modules <Imported Module>` into an independent Site using the Shell for initialization, the header and footer, configuration, and other foundational services (logging, analytics, i18n, etc.)
* Built as :term:`federated modules <Federated Module>` to be loaded into the Shell at runtime via webpack module federation.
* Built and released as an NPM package for build-time inclusion in a frontend :term:`Project`, perhaps alongside other application modules from other libraries.

Environment Agnostic
====================

The :term:`application module libraries <Application Module Library>` will no longer contain ``.env`` or ``env.config`` files for any specific environment, including `Devstack <https://github.com/openedx/devstack>`_ and `Tutor <https://docs.tutor.edly.io/>`_. Config filename patterns will be added to the ``.gitignore`` file. They will continue to support adding a (git ignored) config file into the repository to build or develop it, but we also expect operators to use Projects and check their config files into those project repositories as their primary way of working with the application module libraries.

Please see :doc:`0003-frontend-projects` for more information on projects.

Removed Dependencies
====================

Application module libraries will cease to use the following libraries in favor of ``frontend-base``:

* @openedx/frontend-build
* @edx/frontend-plaform
* @openedx/frontend-plugin-framework
* @edx/frontend-component-header
* @edx/frontend-component-footer
* @openedx/frontend-slot-footer
* @edx/brand
* core-js
* regenerator-runtime

Peer Dependencies
=================

We expect application module libraries to be dependencies of Frontend Projects by default for most operators. Because of this, the following dependencies will become peer dependencies in the application module libraries themselves:

* @openedx/frontend-base
* @openedx/paragon
* react
* react-dom
* react-redux
* react-router
* react-router-dom
* redux

New CLI Tools
=============

The ``fedx-scripts`` CLI tools from ``frontend-build`` will be replaced with the ``openedx`` CLI tools from ``frontend-base``. We'll discuss some of them in detail here, as they help illustrate what the library will be able to do:

* ``dev`` will start a dev server, loading the repository's application modules into the shell in a site.
* ``dev:module`` will start a dev server that provides the application modules via module federation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

* ``build`` will create a standalone deployable artifact that uses the shell (similar to the micro-frontend architecture)
* ``build:module`` will create a standalone deployable artifact that provides the application modules via module federation.
* ``release`` will package the library for distribution on npm.
* ``serve`` will work with ``build`` or ``build:module`` to locally serve the production assets they generated.
* ``pack`` will work with ``release`` to create a ``.tgz`` file suitable for installing in local git checkouts that depend on the library. (this is a development tool)

The ``dev``, ``dev:module``, ``build``, and ``build:module`` CLI commands will rely on the existence of a :term:`Site Config` file (the replacement for .env/env.config files) which will not be checked into the repository.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily a suggestion, but a request for clarification:

Suggested change
The ``dev``, ``dev:module``, ``build``, and ``build:module`` CLI commands will rely on the existence of a :term:`Site Config` file (the replacement for .env/env.config files) which will not be checked into the repository.
The ``dev``, ``dev:module``, ``build``, and ``build:module`` CLI commands will rely on the existence of a :term:`Site Config` file (the replacement for .env/env.config files) which will not be checked into the module repository.

The config file will be checked into a repository (the project's, I suppose), just not the module's... right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good clarification, fixing.


Distributed as NPM Packages
===========================

``frontend-app-*`` repositories that are part of Open edX releases will be expected to be published on NPM as a library which exports its modules. These libraries will primarily be consumed by :term:`projects <Project>`.

Consequences
************

As the module architecture stabilizes, ``frontend-app-*`` maintainers and developers will be encouraged to migrate their micro-frontends into application module libraries, and to adopt the module architecture provided by ``frontend-base``. (There will be a migration guide.)

For micro-frontends that are migrated to application module libraries using the shell, there will be a deployment approach that mimics the micro-frontend architecture, but which will require operators to adopt a new underlying configuration and build process to achieve a similar result. Each ``frontend-app-*`` repository will need a deprecation process for the micro-frontend configuration and build infrastructure.

Thinking in Modules
===================

Our definition of :term:`module` aligns with the `industry standard definition <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules>`_. It is also used in the context of `module federation <https://module-federation.io>`_. It's a self-contained part of the frontend that represents a specific part of the :term:`Site`, and can be loaded in a variety of ways. We have several sub-types of module:

* An *application module* represents a well-bounded sub-area of the Open edX frontend at a particular route path. This might be "courseware", "the login page", or "account settings". There are a number of application modules that are *required* for a functioning Open edX frontend Site.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per a previous review comment, I feel "application module" can double as the name for the whole thing (sans library at the end).

Maybe another way to think about it is that different modules should live in different repos, lest we fall into the mono-repo issues we've discussed in the past.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this offline, but for posterity - there are two related rationales for keeping modules (particularly application modules, which are generally pretty big) in the same repository together. These are:

  1. If they share code with other modules in the library. If we split them up and have to create a secondary library to share code between them, we probably haven't made our lives better.
  2. If they're part of the same conceptual 'domain' of the site. This was the original idea behind the MFE boundaries we have today, though we didn't execute it consistently. Some are too big, some are too small. It seems very reasonable to me that the learning-related stuff could be in "frontend-app-learning", and the user account/authentication related stuff would be in something like "frontend-app-user", which doesn't exist.

* A "plugin module" represents an optional UI component that is generally added somewhere in an application module, or in the shell. The header and footer, for instance, would be overridden with alternate implementations via plugin modules. New tabs added to the course homepage are also plugin modules.
* *Service modules* which act as implementations of the logging or analytics services.
* *Script modules* which allow attaching arbitrary scripts to the page.

Our ``frontend-app-*`` repositories go from being "micro-frontend applications" to being a collection of application modules centered around a particular domain (learning, authoring, authn, etc.) The question of which application modules belong in which repositories, and where the right boundaries are, is beyond the scope of this ADR.

Unsupported Customizations
==========================

The :term:`micro-frontend architecture` took an extreme approach to "flexibility", allowing MFEs to diverge from each other in a variety of ways as described in :doc:`OEP-65 <../../oep-0065-arch-frontend-composability>`. As a result, in the process of migrating them to the :term:`module architecture`, there could be unforeseen refactoring that may need to happen in some MFEs that don't map into modules well, or which have customizations that aren't supported by the Shell. While we hope to provide enough extensibility mechanisms to reduce the need for forking or hacky customizations, there will be customizations we haven't anticipated, which the community will need to work around or find ways to support.

Consistent Dependency Versions
==============================

Addressing our *lack* of dependency version consistency is one of the primary drivers of OEP-65.

The shell will support specific versions of shared dependencies (such as React, Paragon, or React Router). All applications loaded into the shell's Site will be expected to use (or at least be compatible) with that version. We intend to create lock-step version consistency of shared dependencies across all applications in the platform. We envision each Open edX release supporting a particular major version of each shared dependency.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+100


References
**********

* :doc:`OEP-65: Frontend Composability <../../oep-0065-arch-frontend-composability>`
* :doc:`OEP-65 Frontend Glossary <./frontend-glossary>`
* :doc:`ADR-0001: Unified Platform Repository <./0001-unified-platform-repository>`
* :doc:`ADR-0003: Frontend Projects <./0003-frontend-projects>`

Change History
**************

2024-08-28
==========

* Document created
* `Pull request #626 <https://github.com/openedx/open-edx-proposals/pull/626>`_

2024-09-13
==========

* Updating the language use to match and reference the frontend glossary.
Loading