Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[#microfrontend-content-loading]
= Microfrontend Content Loading Mechanism

== Overview

This document explains how Microfrontend content is loaded in the OneCX platform using Module Federation.

It helps you:

- Understand available loading approaches
- Choose the correct integration approach
- Configure microfrontends correctly

Microfrontend integration is primarily determined by two factors:

* xref:./content-type.adoc[**Content Type**]
** Module
** Remote Component

* xref:./expose-method.adoc[**Expose Method**]
** Angular
** Web Component

These factors depend on the type of content exposed by the microfrontend and must be configured correctly in the Application Store.

IMPORTANT: *It is NOT recommended to use the Angular expose method.* Using the Angular expose method creates tight coupling between microfrontends and restricts the platform’s ability to support multiple frameworks and versions.

NOTE: OneCX uses https://webpack.js.org/concepts/module-federation/[Module Federation] with Webpack to load and expose microfrontends.

.Navigation
[cols="1,1"]
|===
| xref:../index.adoc[← Previous: Introduction to Module Federation]
| xref:./content-type.adoc[Next: Content Type →]
|===
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[#content-type]
= Content Type in Microfrontend Loading

== Overview

Content Type defines what kind of UI is dynamically loaded as a microfrontend in the OneCX platform.

It determines whether you are loading a full feature (Module) or a reusable UI component (Remote Component).

Selecting the correct content type is important, as it affects how the microfrontend is loaded and displayed.

== Content Type Selection

.Content Type Selection
[.stripes-even,cols="33,33,~"]
|===
| Use Case | Content Type | Loading Mechanism

| Full page or feature with routing
| Module
| xref:./shell-router.adoc[Shell UI Router]

| Reusable UI component embedded in a page
| Remote Component
| xref:./slot-component.adoc[Slot Component]
|===

.Navigation
[cols="1,1"]
|===
| xref:./content-loading.adoc[← Previous: Microfrontend Content Loading]
| xref:./shell-router.adoc[Next: Shell UI Router →]
|===
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[#expose-method]
= Expose Method in Microfrontend Loading

== Overview

The expose method is a factor considered by the respective loading mechanism (Shell UI Router or Slot Component) to ensure correct content loading.

== Usage in loading mechanisms
[cols="1,2", options="header"]
|===
| Loading type | Impact
| Module loading | The `loadChildren` method and router configuration are affected.
| Remote component loading | A different mechanism for dynamic content creation is chosen.
|===

More details about the impact of the expose method can be found xref:./webcomponents/index.adoc[here].

.Navigation
[cols="1"]
|===
| xref:../index.adoc[← Previous: Introduction to Module Federation]
|===
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[#module-federation-loading]
= Module Federation Loading Explained

Independent of the content type and expose method, the OneCX platform loads exposed content using **Module Federation**.

During this process, the exposed content is loaded using the file specified in the webpack configuration for the respective content.
As this example uses Webpack, this configuration is specified in the `webpack.config.js` file.

.Example
[source, javascript]
---
const config = withModuleFederationPlugin({
name: 'my-application-ui',
filename: 'remoteEntry.js',
exposes: {
'./MyDefaultModule': './src/main.ts',
'./MyRemoteComponent': './src/app/remotes/my-comp/my-comp.component.main.ts'
},
...
})
---
== Notes

* `MyDefaultModule` - The file is used for module loading.
* `MyRemoteComponent` - The file is used for remote component loading.

== Loading process

Files defined in the configuration are used to load the exposed content. These files should contain all the required setup to display content.

The implementation inside these files depends on the chosen expose method.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[#shell-router]
= Shell UI Router

== Overview

The **Shell UI Router** acts as the central orchestrator, building the workspace and setting up routing based on backend configuration. It maps application paths to their respective microfrontend modules. At runtime, it uses **Module Federation** to dynamically load the required module when a route is activated. The loaded module is then rendered in the content area, enabling independent deployment and seamless navigation.

=== Workspace and Route Configuration

The Shell UI Router builds the workspace using configuration data provided by backend services. This configuration contains all applications registered for a workspace along with their associated paths.

Each application must define a unique path. This path is used by the Shell UI Router to create routing rules and to identify which microfrontend module should be loaded for a given URL.

Based on this configuration, the Shell UI Router maps each path to its corresponding microfrontend module. These mappings form the foundation for routing and ensure that the correct module is loaded when a user navigates within the workspace.

=== Router Initialization

Before handling any navigation, the Shell UI Router initializes the router using the workspace configuration. It reads the configured application paths and creates routing rules for each one.

These rules define how URLs are matched to microfrontend modules during runtime. For every application, a corresponding route is registered in the router.

This setup ensures that when a user navigates to a specific path, the Shell UI Router can correctly identify and trigger loading of the associated module.

=== Route Structure and Properties

Each application is registered as a route in the Shell UI Router. Every route includes a defined path and a `loadChildren` method, along with additional properties used during routing.

The `path` determines how a URL is matched, while `loadChildren` defines how the corresponding microfrontend module is loaded when the route is activated.

These route definitions allow the Shell UI Router to connect navigation events with the correct module loading behavior, ensuring that the appropriate content is displayed.

=== Module Loading using Module Federation

When a route is activated, the Shell UI uses the `loadChildren` method to load the corresponding microfrontend module.

The `loadChildren` method is responsible for loading the remote module into the Shell UI’s memory using `@angular-architects/module-federation`. This enables dynamic loading of independently deployed applications at runtime.

Once the remote module is successfully loaded, it is passed to the router, which renders the module’s content in the content area of the application.

=== Runtime Navigation Flow (Example)

Consider a workspace that includes a User Profile application with the path `/user`.

When the application starts, the Shell UI registers a route for `/user` based on the workspace configuration. If the user navigates to a URL starting with `/user`, the router matches this route.

The `loadChildren` method is then triggered, and the Shell UI uses Module Federation to load the User Profile microfrontend module.

Once loaded, the router renders the module in the content area, allowing the user to interact with the application.

.Navigation
[cols="1,1"]
|===
| xref:./content-type.adoc[← Previous: Content Type]
| xref:./slot-component.adoc[Next: Slot Component →]
|===
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[#slot-component]
= Slot Component

== Overview
The slot component mechanism in OneCX is used for dynamically rendering remote components in specific locations on a page using **Module Federation**. Slots are configurable at runtime.

Remote component loading is handled by the slot component. The remote component loading mechanism can be found xref:../../architecture/remote-components.adoc[here].

== Key aspects

* The loading process starts when a slot component is rendered on a page.
* Exposed remote component content is loaded using `@angular-architects/module-federation`.
* After successful loading, the component is rendered inside the slot component.
* Rendering uses a dynamic content creation mechanism based on the chosen expose method.

== Slot rendering process
The following flow describes how slot rendering works:

* App1 owns the page and defines a **slot location**.
* App2 exposes a **remote component** using **module federation** that can be used in the slot.
* Both App1 and App2 are available in the **workspace**.
* The slot defined in App1 is **activated** in the **workspace**.
* A remote component from App2 is **assigned** to the slot in App1.
* When the slot is displayed, App1 dynamically loads the component **exposed** by App2 using **module federation**.
* The component is then **rendered** in the slot using the technology defined in the **remote component configuration**.

.Navigation
[cols="1,1"]
|===
| xref:./shell-router.adoc[← Previous: Shell UI Router]
| xref:./expose-method.adoc[Next: Expose Method →]
|===
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
[#onecx-adaptation-to-webcomponent-method]
= OneCX Adaptation to Webcomponent Method

As stated in xref:./microfrontend-content-loading.adoc[Microfrontend content loading documentation], every method of Microfrontend's content exposal has an impact on the OneCX platform behavior for both module and Remote Component loading. The adaptations made by OneCX to work with Web Components were briefly mentioned in the Web Components preview, however depending on the content type, the behavior varies.

[#module-loading-behavior]
== Module Loading Behavior

=== Overview

This section explains how the Shell UI loads and renders Microfrontend modules using the Webcomponent expose method. It describes how routing, module federation, and Web Components work together, where the Shell loads the module and Web Components handle rendering through custom elements.

* *Shell UI Responsibility* - The Shell UI App is responsible for displaying Microfrontend's module when router navigation is matched for a desired Microfrontend.

* *Webcomponent Adaptation in loadChildren* - With Webcomponent method, Shell UI will adapt the loadChildren method to:

. load desired remote module using https://www.npmjs.com/package/@angular-architects/module-federation[@angular-architects/module-federation] (no change).
. use **WebComponentLoaderModule** as the module to be lazy-loaded (instead of the Microfrontend's module).

* *loadChildren Behavior* - The https://angular.dev/guide/ngmodules/lazy-loading[loadChildren method bound to a Route] is an asynchronous method that in the end should return a module to be displayed when activating a certain Route.

* *Module Loading with Webcomponent* - With Webcomponent method, the desired Microfrontend's module is still being loaded using https://www.npmjs.com/package/@angular-architects/module-federation[@angular-architects/module-federation].

* *Custom Elements Registration* - During that loading, it should register a component in the Custom Elements Registry, as mentioned in the previous section.

* *Shell UI Rendering Responsibility* - For OneCX platform, it means that it no longer should load the Microfrontend's module directly but ensure that the HTML code has the correct Custom Element in order to display the module.

* *WebComponentLoaderModule* - **WebComponentLoaderModule** is a simple Angular module with a Router set up to always display **WebComponentLoaderComponent**.

* *WebComponentLoaderComponent Responsibility* - This component is responsible for rendering the HTML element required to display the module with Web Components Custom Elements.

* *Router Navigation Handling* - Whenever Shell UI's router detects a change of the Microfrontend (another path is matched than the current one), it calls **loadChildren method** to load the desired module and returns **WebComponentLoaderModule**.

* *Component Initialization* - The module then creates and initializes **WebComponentLoaderComponent**, which, after initializations, creates the HTML element.

* *Web Components Binding* - Then Web Components using Custom Elements technology bounds the Microfrontend's module to the created element.

* *Reference* - For a detailed guide on how to expose Microfrontend's module via Webcomponent method, please refer xref:../../onecx/microfrontend-bootstrapping/module-bootstrapping.adoc[here].

[#remote-component-behavior]
== Remote Component Behavior

=== Overview

This section explains how the Slot Component renders Microfrontend Remote Components using the Webcomponent method. Instead of directly creating Angular components, the Slot Component creates an HTML host element, while the microfrontend registers and binds its component using Web Components and Custom Elements.

* *Slot Component Responsibility*
Slot Component is responsible for displaying Microfrontend's Remote Components during Slot Component initialization.

* *Webcomponent Adaptation in Slot Component* - With the Webcomponent method, the Slot Component will adapt the steps to:

. load desired remote content using https://www.npmjs.com/package/@angular-architects/module-federation[@angular-architects/module-federation] (no change).
. create HTML element directly inside a container (instead of creating Microfrontend's Remote Component instance).

* *Dynamic Content Creation*
The Slot Component content is based on https://angular.dev/api/core/ViewContainerRef[Angular ViewContainerRef] to dynamically create content inside the Slot Component.

* *Module Loading with Webcomponent* - With Webcomponent method, the desired Microfrontend's Remote Component is still being loaded using https://www.npmjs.com/package/@angular-architects/module-federation[@angular-architects/module-federation].

* *Custom Elements Registration* - During that loading, it should register a component in the Custom Elements Registry, as mentioned in the previous section.

* *OneCX Rendering Responsibility* - For OneCX platform, it means that it no longer should create the Microfrontend's component directly but ensure that the HTML code has the correct element in order to display the component.

* *Webcomponent Method Difference* - The difference with the Webcomponent method is that, from the OneCX platform's perspective, no component needs to be created. Instead, a "host" element must be created to allow Web Components' Custom Elements to display desired content.

* *Reference* - For a detailed guide on how to expose Microfrontend's Remote Components via Webcomponent method, please refer xref:../../onecx/microfrontend-bootstrapping/remote-component-bootstrapping.adoc[here].
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
= Custom Elements in OneCX

== Overview
This article explains how Custom Elements are used in OneCX to dynamically render microfrontend content by binding UI components to HTML elements. It describes the role of the Shell UI, Application Store, and microfrontends in loading, registering, and displaying content using the Web Component approach.

== How It Works

* ** Custom Elements** - Custom Elements are part of the Web Components technology. It is a set of tools used to achieve the binding between components and HTML elements.

* **Configuration** - OneCX platform will create HTML elements specified via configuration whenever a module or Remote Component has to be displayed on a page.

* **Content loading in OneCX** - There are 2 steps that OneCX platform takes when dealing with content loading with Webcomponent expose method:

** Load exposed content via Module Federation into memory
** Create an HTML element on a page to which exposed content should be bound

* **Responsibility of Microfrontend** - In the Microfrontend content loading, it was mentioned that when exposing Microfrontend content, files specified per content should take care of all setup needed to display it.

* **Custom Element Registration** - With Webcomponent method, those files need to contain source code, which will register the Custom Element in the Custom Elements Registry.

* **Binding Components to Elements** - a file used for content loading needs to use Web Components to assign some component to the HTML element that OneCX platform will render.

* **Rendering** - When OneCX platform creates this HTML element on a page, the Custom Elements Registry will use the assigned component and display it on a page.

.Navigation
[cols="1,1"]
|===
| xref:./index.adoc[← Previous: Introduction to Web Components]
| xref:./expose-method-requirements.adoc[Next: Webcomponent Expose Method Requirements →]
|===
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[#expose-microfrontends-content-as-web-components]
== Expose Microfrontend's Content as Web Components
OneCX platform offers different ways of xref:../../../architecture/mfe.adoc[exposing Microfrontend's content]. One of them is **Webcomponent method**.

When exposing content with Webcomponent method, it is required to ensure the correct setup. For exposing Angular content, there are functionalities provided via the <<onecx/angular-webcomponents, @onecx/angular-webcomponents>> library. For a detailed guide on how to expose Microfrontend's content via Webcomponent method, please refer here.

[#angular_issues]
[IMPORTANT]
====
Using **<<onecx/angular-webcomponents, @onecx/angular-webcomponents>>** library, according to the guide, is the recommended way of exposing Angular content. The set of functionalities provided via the library is taking care of all requirements related to the Web Components adaptation. Apart from automatic registration to the Custom Elements Registry, they ensure that the following issues are covered:

* Every module and Remote Component is going to have its own router. Routers (Shell's router, displayed module's router, and router of each displayed Remote Component) need to be synchronized so each can react to the router events.
* A Single Angular version can only create one platform to operate on, which means that for every content loaded within a page, the same platform has to be used for a specific version.
* ngZone of Shell UI has to be shared with all modules and Remote Components to allow Web Components to function correctly.

In-depth explanations for those issues can be found in the https://www.angulararchitects.io/en/blog/multi-framework-and-version-micro-frontends-with-module-federation-the-good-the-bad-the-ugly/[Module Federation multi-framework and version micro frontends document].

====
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
=== Webcomponent Expose Method Requirements

To correctly use Webcomponent expose method, 2 requirements need to be fulfilled:

. Database is correctly configured for module or Remote Component
.. **technology** set to **WebComponent**
.. **tag name** set to agreed **HTML element name**
. Microfrontend is adapted to expose Web Components compliant content
.. desired component needs to be registered as Custom Element in the Custom Elements Registry
.. Angular issues are covered (use the `<<onecx/angular-webcomponents, @onecx/angular-webcomponents>>` library to cover them by default)
... multiple routers synchronization
... ngZone sharing
... platform sharing

NOTE: Database configuration is easy to set up using the Application Store Application.

IMPORTANT: To ensure Microfrontend compliance with Web Components for Angular modules and Remote Components, it is recommended to use the **<<onecx/angular-webcomponents, @onecx/angular-webcomponents>>** library.

.Navigation
[cols="1"]
|===
| xref:./custom-elements.adoc[← Previous: Custom Elements]
|===
Loading