Skip to content

Commit

Permalink
squash!: Update ADR to reflech WIP openedx#440
Browse files Browse the repository at this point in the history
  • Loading branch information
xitij2000 committed Aug 30, 2023
1 parent ce9494e commit 9065b37
Showing 1 changed file with 39 additions and 83 deletions.
122 changes: 39 additions & 83 deletions docs/decisions/0007-compile-common-theme-for-all-mfes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,51 +29,54 @@ SCSS.
This effectively means that all MFEs share a large chunk of common styling code
with a comparatively much smaller set of styles applied over that.

There is scope here to properly split the MFE stylesheet into multiple parts,
one being the common code as represented by the above imports, and another for
MFE-specific code, and build them separately.
With the introduction of a new styling mechanism in the `design tokens ADR`_ it
will be possible to build a Paragon theme that contains a majority of CSS code
that is independent of branding variables, which are loaded from a separate
variables CSS file.

One thing that prevents this is that MFEs need these SCSS imports to get
variables. In a number of cases these can be replaced with either
Paragon/Bootstrap classes, or CSS variables. A separate ADR in `Paragon
<https://github.com/openedx/paragon/pull/1388>`_ covers the situations where
this isn't possible yet.
With that change we can now compile a common cross-MFE Paragon CSS that can be
loaded from a common source for all MFEs, and a separate CSS containng all the
theming variables. There can also be multiple variable definitions for different
themes that correspond to a dark and light theme or potentially other variants.

Decision
********

Common cores styling that is to be applied to all MFEs should be part of a
separate stylesheet and built separately from the MFE-specific stylesheet.
Paragon CSS code can be compiled once and loaded in all MFEs from a URL provided
by an environment variable or via runtime configuration. The runtime
configuration will allow having a single deployment of an MFE cater to multiple
sites by varying the theme loaded for each site.

Both these stylesheets will be included in each MFE, however the common
stylesheet can be loaded from a common source for all MFEs. This will allow for
deploying the common theme stylesheet without redeploying MFEs.
The CSS code will be split into two parts, the first is the core stylesheet that
contains foundational code such as layout, typography etc. One or more
additional stylesheets will need to be provided which will include the CSS
variables that define the colours, spacing, font faces, sizes etc.

The mechanism for loading this common stylesheet will need to be different from
the mechanism for loading the MFE stylesheet. A JavaScript theme loader will
contain the location of the SCSS file and will add this stylesheet to the
document.
There is scope for provding multiple stylesheets that contain variable
definitions. These can correspond to a standard light theme, a dark theme and
potentially other themes.

The common theme package will be similar to the branding package, but can be
deployed independently of MFEs. It will produce a CSS stylesheet, and a
JavaScript loader that will load this stylesheet. When deploying MFEs, they can
be provided a configuration variable that contains the location where this
theme loader is deployed.
In order to enable this mechanism there will be changes to the frontned platform
that include a mechanism for checking if a common theme location is defined,
whether via an environment variable or in runtime configuration. If so, code in
the AppProvider function that is used by all MFEs will load the theme from here
automatically.

The frontend-platform repo can host code that simplifies using themes. It can
check if a theme loader is configured, and if so, dynamically load the theme
from there. Otherwise, it can continue using the existing mechanism of building
and deploying the theme for each MFE for backwards-compatibility. It can also
provide hooks for loading the theme and potentially/eventually also selecting
a theme.
There will also be an API for runtime loading of a theme, which can allow MFEs
to provide a UI for runtime theme switching.

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

With a single common stylesheet for all MFE, they should load quicker since the
stylesheet can be cached once for all MFEs. It also makes theme rebuilds much
quicker, and eliminates the need for rebuilding each MFE for minor change to
the theme.
Since these stylesheets are shared across all MFEs, it can be uploaded to a CDN,
speeding up loading of all MFEs since a cached stylesheet will be loaded for all
MFEs once a user has used any MFE. Likewise any updates pushed to the CDN can
automatically be pushed to all MFEs through runtime configuration without
needing to rebuild all of them. Changes to theming variables can also
automatically reflect across all MFEs since they load from a shared location.

This will also make theme rebuilds much quicker, and eliminate the need for
rebuilding each MFE for minor change to the theme.

For context, on a sample development machine, rebuilding an MFE takes roughly
one minute, of this, on the same machine, around 3-4 seconds is the time it
Expand All @@ -82,58 +85,11 @@ takes to build the theme.
By continuing to support the existing theming mechanism, the current mechanism
for theming can continue working for those who need it.

Since there is a JavaScript-based loader involved, there is potential for
flashing of unstyled content during loading, however this can be avoided by
making the theme loader part of the init process so it runs before the app is
considered ready.

Another major consequence of this change would be that the CSS code for Paragon
would be loaded using a different mechanism than the JavaScript code of Paragon.
The CSS code would be compiled into the theme whereas the JS code will be loaded
directly. This means that if different versions of Paragon are used for an MFE
vs the common theme, then there is a chance that an incompatible version of the
CSS could be loaded for the MFE. This will make it all the more important to
ensure that version of Paragon used across all MFEs is compatible. This will be
simpler for named releases than for those running latest code changes.

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

- **Loading the common CSS directly instead of with a JavaScript based loader**

This ADR proposes using an intermediary JavaScript loader to load CSS rather
then just having the configuration variable point to the stylesheet itself.
This is done for performance reasons.

Currently, when an MFE is built, each static asset contains the hash of the
asset in the file name. The ``index.html`` file includes these generated file
names, and if any asset changes the ``index.html`` file is updated.

When a user reloads an MFE page the index page is reloaded, and if any assets
have changed, their file names will have as well and they will be loaded
fresh. Unchanged assets will keep using the same name and can load from the
cache for a very long time.

If the file names don't change with the content, then there is a risk of
loading older code from the cache, or (if caching is disabled) of loading a
huge chunk of code with each refresh and having a huge hit on performance.

So to maximise the amount of time for which stylesheets are cached, and
minimise the amount of code that needs to be loaded on each refresh, we need
to have a light intermediary loader that provides the location of the
stylesheet. The bulk of the CSS can then be cached for as long as it is
unchanged.

- **Have the theme loading code in each MFE**

This doesn't change much about the rest of the mechanism of this ADR, but it
causes a lot of code duplication across MFEs. Just like ``frontend-platform``
handles authentication for all MFEs, it can also handle dealing with the theme
loader.

A theme switching UI can also potentially be made part of the header or footer
component to make it available across all MFEs easily.

References
**********

- `ADR to introduce CSS variables to parargon
<https://github.com/openedx/paragon/pull/1388>`_
- `Design tokens ADR
<https://github.com/openedx/paragon/pull/1929>`_

0 comments on commit 9065b37

Please sign in to comment.