From bf07aaaa8dbc42f29d3eca8a7daef234acfeee63 Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 8 Apr 2026 04:26:54 +0000 Subject: [PATCH 1/2] docs: microfronent content loading restructured --- .../concepts/content-loading.adoc | 35 ++++++++++++ .../concepts/content-type.adoc | 33 +++++++++++ .../concepts/expose-method.adoc | 22 ++++++++ .../concepts/module-federation-loading.adoc | 31 +++++++++++ .../concepts/shell-router.adoc | 55 +++++++++++++++++++ .../concepts/slot-component.adoc | 32 +++++++++++ .../pages/module-federation - v2/index.adoc | 35 ++++++++++++ 7 files changed, 243 insertions(+) create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/content-loading.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/content-type.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/expose-method.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/module-federation-loading.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/shell-router.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/slot-component.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/index.adoc diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/content-loading.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/content-loading.adoc new file mode 100644 index 000000000..af24d6af1 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/content-loading.adoc @@ -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 →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/content-type.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/content-type.adoc new file mode 100644 index 000000000..e84544991 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/content-type.adoc @@ -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 →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/expose-method.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/expose-method.adoc new file mode 100644 index 000000000..d41f74bca --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/expose-method.adoc @@ -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] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/module-federation-loading.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/module-federation-loading.adoc new file mode 100644 index 000000000..d23187565 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/module-federation-loading.adoc @@ -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. diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/shell-router.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/shell-router.adoc new file mode 100644 index 000000000..21e3c0eb1 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/shell-router.adoc @@ -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 →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/slot-component.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/slot-component.adoc new file mode 100644 index 000000000..abc725980 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/slot-component.adoc @@ -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 →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/index.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/index.adoc new file mode 100644 index 000000000..5187d10d9 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/index.adoc @@ -0,0 +1,35 @@ +:idprefix: +:idseparator: - + +[#module-federation-introduction] += Module Federation Introduction + +https://module-federation.io/guide/start/[Module Federation] is a mechanism that allows sharing code and resources among multiple JavaScript applications. + +**Module Federation** is used to support a **microfrontend-based architecture** where multiple applications can work together as a single user interface. + +**In OneCX**, Module Federation enables dynamic loading of UI modules, allowing applications to be developed, built, and deployed independently. + +This documentation section covers module federation-related concepts, implementation details, configuration, and best practices. + +Before proceeding, familiarize yourself with the following concepts: + +.Prerequisites +[.stripes-even,cols="20,~"] +|=== +| Name | Description + +| https://webpack.js.org/concepts/[Webpack] | Static module bundler for *JavaScript applications* that supports module federation +| https://module-federation.io/[Module Federation] | Enables scalable, independently deployable frontend architecture with *runtime integration* +| https://developer.mozilla.org/en-US/docs/Web/API/Web_components[Webcomponents] | Technology used to render applications in OneCX shell +| https://micro-frontends.org/[Microfrontends] | Extends the concepts of microservices to the frontend world +| https://onecx.github.io/docs/documentation/current/index.html[OneCX] | An *innovative open-source platform* solution enabling seamless *microfrontends integration* +|=== + + +.Concepts +[.stripes-even,cols="20,~"] +|=== +| Name | Description +| xref:./concepts/content-loading.adoc[Microfrontend content loading] | Explains how content loading is handled in OneCX +|=== \ No newline at end of file From d5240378ee81eb8f161dc36228b5bc416e025cbf Mon Sep 17 00:00:00 2001 From: Priyanka Date: Wed, 15 Apr 2026 06:37:19 +0000 Subject: [PATCH 2/2] fix: links --- .../adapt-webcomponent-method.adoc | 66 ++++++ .../webcomponents/custom-elements.adoc | 30 +++ .../expose-content-as-webcomponent.adoc | 18 ++ .../expose-method-requirements.adoc | 23 +++ .../concepts/webcomponents/index.adoc | 22 ++ .../webcomponents/webcomponent-preview.adoc | 10 + .../pages/module-federation - v2/index.adoc | 22 +- .../onecx/angular-webcomponents.adoc | 117 +++++++++++ .../module-federation - v2/onecx/index.adoc | 15 ++ .../angular-expose-method.adoc | 36 ++++ .../bootstrapping-explained.adoc | 17 ++ .../microfrontend-bootstrapping/index.adoc | 25 +++ .../module-bootstrapping.adoc | 151 ++++++++++++++ .../module-deep-dive.adoc | 103 ++++++++++ .../microfrontend-bootstrapping/overview.adoc | 5 + .../remote-component-bootstrapping.adoc | 189 ++++++++++++++++++ .../remote-component-deep-dive.adoc | 114 +++++++++++ .../webcomponent-expose-method.adoc | 18 ++ .../onecx/microfrontend-configuration.adoc | 124 ++++++++++++ 19 files changed, 1099 insertions(+), 6 deletions(-) create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/adapt-webcomponent-method.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/custom-elements.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/expose-content-as-webcomponent.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/expose-method-requirements.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/index.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/webcomponent-preview.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/angular-webcomponents.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/index.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/angular-expose-method.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/bootstrapping-explained.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/index.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/module-bootstrapping.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/module-deep-dive.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/overview.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/remote-component-bootstrapping.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/remote-component-deep-dive.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/webcomponent-expose-method.adoc create mode 100644 docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-configuration.adoc diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/adapt-webcomponent-method.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/adapt-webcomponent-method.adoc new file mode 100644 index 000000000..7c055f01f --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/adapt-webcomponent-method.adoc @@ -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]. \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/custom-elements.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/custom-elements.adoc new file mode 100644 index 000000000..65e26432e --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/custom-elements.adoc @@ -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 →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/expose-content-as-webcomponent.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/expose-content-as-webcomponent.adoc new file mode 100644 index 000000000..49164a914 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/expose-content-as-webcomponent.adoc @@ -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 <> library. For a detailed guide on how to expose Microfrontend's content via Webcomponent method, please refer here. + +[#angular_issues] +[IMPORTANT] +==== +Using **<>** 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]. + +==== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/expose-method-requirements.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/expose-method-requirements.adoc new file mode 100644 index 000000000..da808087c --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/expose-method-requirements.adoc @@ -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 `<>` 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 **<>** library. + +.Navigation +[cols="1"] +|=== +| xref:./custom-elements.adoc[← Previous: Custom Elements] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/index.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/index.adoc new file mode 100644 index 000000000..0705b1d97 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/index.adoc @@ -0,0 +1,22 @@ +[#webcomponents-in-onecx] + +:idprefix: +:idseparator: - +:imagesdir: ../../../images + += Web Components in OneCX + +[#overview] +== Overview +Web Components is a suite of different technologies used to create reusable custom elements with encapsulated functionality. In the OneCX context, they are useful for dynamic content creation for both modules and the display of Remote Components in Microfrontends. Prior to reading this document, it is recommended to read the documentation of xref:../content-loading.adoc[microfrontend content loading] to get familiar with the content loading mechanisms available within the OneCX platform. + +IMPORTANT: Webcomponent expose method enables the OneCX platform to use UI Apps developed with different frameworks and versions. It is the **recommended method for all Applications**. + +NOTE: Web Components technologies are used within OneCX platform. However, OneCX offers its own functionalities that should be used to expose Microfrontend's content using the Webcomponent expose method. Those functionalities are based on Web Components technologies, so there is no need to get familiar with them. Nevertheless, more resources about Web Components can be found https://developer.mozilla.org/en-US/docs/Web/API/Web_components[here] + +=== Key concepts + +* xref:./webcomponent-preview.adoc[Web Components Preview] +* xref:./expose-content-as-webcomponent.adoc[Expose Microfrontend's Content as Web Components] +* xref:./adapt-webcomponent-method.adoc[OneCX Adaptation to Webcomponent Method] +* xref:../../onecx/angular-webcomponents.adoc[@onecx/angular-webcomponents Details] \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/webcomponent-preview.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/webcomponent-preview.adoc new file mode 100644 index 000000000..44b5ef2c1 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/concepts/webcomponents/webcomponent-preview.adoc @@ -0,0 +1,10 @@ +[#webcomponents-preview] +== Web Components Preview + +Web Components are used in OneCX context for dynamic content creation. OneCX platform uses Web Components technologies to bound UI components to HTML elements. OneCX platform will use information from the Application Store to determine what HTML elements have to be rendered to allow certain modules and Remote Components to be bound to page content. + +With Webcomponent expose method, the OneCX platform is only loading the code required for Microfrontend's content into the Shell UI memory and creating a "host" element for Remote Components or modules to attach to using Web Components. The Microfrontend's exposed content is partially responsible for the content creation. Microfrontends have to adapt exposed modules and components, so they are using Web Components Custom Elements. + +=== Key concepts + * xref:./custom-elements.adoc[Custom Elements] + * xref:./expose-method-requirements.adoc[Webcomponent Expose Method Requirements] \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/index.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/index.adoc index 5187d10d9..d1cf332ff 100644 --- a/docs/modules/onecx-docs-overview/pages/module-federation - v2/index.adoc +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/index.adoc @@ -4,7 +4,7 @@ [#module-federation-introduction] = Module Federation Introduction -https://module-federation.io/guide/start/[Module Federation] is a mechanism that allows sharing code and resources among multiple JavaScript applications. +https://module-federation.io/guide/start/[Module Federation] is a mechanism that allows code and resources to be shared across multiple JavaScript applications. **Module Federation** is used to support a **microfrontend-based architecture** where multiple applications can work together as a single user interface. @@ -19,17 +19,27 @@ Before proceeding, familiarize yourself with the following concepts: |=== | Name | Description -| https://webpack.js.org/concepts/[Webpack] | Static module bundler for *JavaScript applications* that supports module federation +| https://webpack.js.org/concepts/[Webpack] | A static module bundler for *JavaScript applications* that supports Module Federation | https://module-federation.io/[Module Federation] | Enables scalable, independently deployable frontend architecture with *runtime integration* -| https://developer.mozilla.org/en-US/docs/Web/API/Web_components[Webcomponents] | Technology used to render applications in OneCX shell +| https://developer.mozilla.org/en-US/docs/Web/API/Web_components[Web Components] | Technology used to render applications in OneCX shell | https://micro-frontends.org/[Microfrontends] | Extends the concepts of microservices to the frontend world -| https://onecx.github.io/docs/documentation/current/index.html[OneCX] | An *innovative open-source platform* solution enabling seamless *microfrontends integration* +| https://onecx.github.io/docs/documentation/current/index.html[OneCX] | An *innovative open-source platform* solution enabling seamless *microfrontend integration* |=== .Concepts -[.stripes-even,cols="20,~"] +[.stripes-even,cols="25,~"] |=== | Name | Description | xref:./concepts/content-loading.adoc[Microfrontend content loading] | Explains how content loading is handled in OneCX -|=== \ No newline at end of file +| xref:./concepts/webcomponents/index.adoc[Web Components] | Explains how Web Components are used in OneCX to load microfrontends +|=== + +.How to bootstrap and configure microfrontends in OneCX +[.stripes-even,cols="25,~"] +|=== +| Name | Description +| xref:./onecx/microfrontend-bootstrapping/index.adoc[Microfrontend bootstrapping] | Explains how to set the initial structure and configuration for a microfrontend application in OneCX +| xref:./onecx/microfrontend-configuration.adoc[Microfrontend configuration] | Explains how to configure a microfrontend to use Module Federation for loading and dependency sharing in OneCX +| xref:./onecx/angular-webcomponents.adoc[Angular Webcomponents] | Explains that exposing modules and remote components via microfrontends is the recommended approach within the OneCX platform. +|=== diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/angular-webcomponents.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/angular-webcomponents.adoc new file mode 100644 index 000000000..8e9129130 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/angular-webcomponents.adoc @@ -0,0 +1,117 @@ +[#onecx-angular-webcomponents] += @onecx/angular-webcomponents Details + +Using <> to expose modules and Remote Components via Microfrontends is the recommended way within the OneCX platform. There are guides available that showcase how to transform already-created Microfrontend's content to use Webcomponent method. In this section, all the specific functions available within the angular-webcomponents library are explained. + +[#bootstrapmodule] +== bootstrapModule Function +Please refer to this example of xref:./microfrontend-bootstrapping/module-bootstrapping.adoc#bootstrap-module[bootstrapModule]. Use **bootstrapModule** function for Angular module bootstrapping. + +This function ensures that the module is bootstrapped correctly and takes care of: + +* ngZone sharing +* platform sharing + +.bootstrapModule arguments +|=== +|**Argument**|**Type**|**Description** +|module +|Type +|Angular Module to load + +|appType +|'shell' or 'microfrontend' +|Use 'microfrontend' for exposing modules + +|production +|boolean +|if the application should run in production mode +|=== + +[#bootstrap-remote-component] +== bootstrapRemoteComponent Function +Please refer to this example of xref:./microfrontend-bootstrapping/remote-component-bootstrapping.adoc#bootstrap-remote-component[bootstrapRemoteComponent]. Use **bootstrapRemoteComponent** function for Angular Remote Component bootstrapping. + +This function ensures that the Remote Component is bootstrapped correctly and takes care of: + +* Remote Component router connection +* ngZone sharing +* platform sharing + +.bootstrapRemoteComponent arguments +|=== +|**Argument**|**Type**|**Description** +|component +|Type +|Angular Component to load + +|elementName +|string +|HTML element name to be used for Custom Elements registration + +|production +|boolean +|if the application should run in production mode + +|providers +|Array<(Provider \| EnvironmentProviders)> +|Array of providers for Remote Component to run +|=== + +[#create-app-entrypoint] +== createAppEntrypoint Function +Please refer to this example of xref:./microfrontend-bootstrapping/module-bootstrapping.adoc#module-bootstrapping-example[createAppEntrypoint]. Use **createAppEntrypoint** function to create an entrypoint component for Microfrontend's module in the Microfrontend's ngDoBootstrap function. + +.createAppEntrypoint arguments +|=== +|**Argument**|**Type**|**Description** +|component +|Type +|Angular Component to load, representing module entrypoint. This component should have **router-outlet** in its template to enable routing for a module. + +|elementName +|string +|HTML element name to be used for Custom Element's registration of entrypoint + +|injector +|Injector +|Module's injector (usually `this.injector`) to be used for dependency injection +|=== + +[#initialize-router] +== initializeRouter Function +Use **initializeRouter** function as APP_INITIALIZER in the Microfrontend's module definition. + +This function ensures that the bootstrapped module's router is connected with other routers. + +[source,typescript] +@NgModule({ + ... + providers: [ + { + provide: APP_INITIALIZER, + useFactory: initializeRouter, + multi: true, + deps: [Router, AppStateService] + } + ] +}) +export class RemoteModule ... + +[#starts-with] +== startsWith Function +Please refer to this example of xref:./microfrontend-bootstrapping/module-bootstrapping.adoc#module-bootstrapping-example[startsWith]. Use **startsWith** function when constructing Routes for Microfrontend's module. + +.createAppEntrypoint arguments +|=== +|**Argument**|**Type**|**Description** +|prefix +|string +|Prefix to match in order to display certain module content. +|=== + +.Navigation +[cols="1"] +|=== +| xref:./index.adoc[← Back to Module federation bootstrapping and configuration in OneCX] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/index.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/index.adoc new file mode 100644 index 000000000..eaa3dfe3c --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/index.adoc @@ -0,0 +1,15 @@ +[#module-federation-bootstrapping-and-configuration-in-onecx] += Module Federation bootstrapping and configuration in OneCX + +This guide contains information about how to set up and use Module Federation in OneCX, including bootstrapping and configuration of module and remote components. + +== Key concepts + +.How to bootstrap and configure microfrontends in OneCX +[.stripes-even,cols="25,~"] +|=== +| Name | Description +| xref:./microfrontend-bootstrapping/index.adoc[Microfrontend bootstrapping] | Explains how to set initial structure and configuration for a microfrontend application in OneCX +| xref:./microfrontend-configuration.adoc[Microfrontend configuration] | Explains how to configure a microfrontend to use Module Federation for loading and dependency sharing in OneCX +| xref:./angular-webcomponents.adoc[Angular Webcomponents] | Explains that exposing modules and Remote Components via Microfrontends is the recommended way within the OneCX platform. +|=== diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/angular-expose-method.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/angular-expose-method.adoc new file mode 100644 index 000000000..4106ae813 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/angular-expose-method.adoc @@ -0,0 +1,36 @@ +[#content-exposed-using-angular-method] +=== Content Exposed Using Angular Method +IMPORTANT: **It is NOT recommended** to use the Angular expose method. Doing so restrains the platform from using many frameworks with different versions, which means that all Microfrontends would need to use the same technology and version. + +When exposing modules and Remote Components using the Angular method, there are two requirements: + +. Webpack configuration needs to expose the module or component file directly. It means that instead of pointing to a **main.ts** file that is bootstrapping the content, **module.ts** and **component.ts** files should be used directly. +. The **main.ts** file of Microfrontend's modules (content type) needs to bootstrap the module asynchronously. ++ +**main.ts** content should look similar to: +[source,typescript] +import('./bootstrap').catch(err => console.error(err)); ++ +**bootstrap.ts** content should look similar to (or any custom bootstrap of your Microfrontend): ++ +[source,typescript] +.... +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { enableProdMode } from '@angular/core'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); +.... + +.Navigation +[cols="1,1"] +|=== +| xref:bootstrapping-explained.adoc[← Previous: Microfrontend Content Bootstrapping Explained] +| xref:./webcomponent-expose-method.adoc[Next: Content Exposed Using Webcomponent Method →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/bootstrapping-explained.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/bootstrapping-explained.adoc new file mode 100644 index 000000000..4df2822df --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/bootstrapping-explained.adoc @@ -0,0 +1,17 @@ +:mfe-loading_url: xref:../../concepts/content-loading.adoc + +[#microfrontend-content-bootstrapping-explained] +== Microfrontend Content Bootstrapping Explained +{mfe-loading_url}[Microfrontend content loading] is an action triggered by the route change (Shell Application's responsibility of loading modules) or by the Slot Component display (Slot Component's responsibility of loading Remote Components). During this action, Microfrontend's content, exposed via remote entry file, is loaded and bootstrapped using the provided file in xref:../microfrontend-configuration.adoc[Webpack configuration]. + +Depending on the content type and chosen expose method, different adjustments have to be made to ensure correct content bootstrapping. + +* xref:angular-expose-method.adoc[Content Exposed Using Angular Method] +* xref:webcomponent-expose-method.adoc[Content Exposed Using Webcomponent Method] + +.Navigation +[cols="1,1"] +|=== +| xref:./index.adoc[← Previous: Microfrontend Bootstrapping] +| xref:./angular-expose-method.adoc[Next: Content Exposed Using Angular Method →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/index.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/index.adoc new file mode 100644 index 000000000..8da3c6aeb --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/index.adoc @@ -0,0 +1,25 @@ +[#microfrontend-bootstrapping] += Microfrontend Bootstrapping + +include::./overview.adoc[] + +== Key concepts + +* xref:bootstrapping-explained.adoc[Microfrontend Content Bootstrapping Explained] + +== Module bootstrapping + +* xref:module-bootstrapping.adoc[Module Bootstrapping and Configuration] +* xref:module-deep-dive.adoc[Module Example Deep Dive] + +== Remote Component bootstrapping + +* xref:remote-component-bootstrapping.adoc[Remote Component Bootstrapping and Configuration] +* xref:remote-component-deep-dive.adoc[Remote Component Example Deep Dive] + +.Navigation +[cols="1,1"] +|=== +| xref:../index.adoc[← Previous: Module Federation bootstrapping and configuration in OneCX] +| xref:./bootstrapping-explained.adoc[Next: Microfrontend Content Bootstrapping Explained →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/module-bootstrapping.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/module-bootstrapping.adoc new file mode 100644 index 000000000..595436bd6 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/module-bootstrapping.adoc @@ -0,0 +1,151 @@ +:angular_issues_url: xref:../../concepts/webcomponents/expose-content-as-webcomponent.adoc#angular_issues + += Module Bootstrapping and Configuration + +The following requirements need to be fulfilled when exposing modules using the Webcomponent method: + +. Webpack configuration needs to expose the *main.ts* file of the module. +. The **main.ts** file of the module needs to bootstrap the module asynchronously. +. Module bootstrapping has to cover {angular_issues_url}[Angular issues] (for Angular-based modules only) +. Module class +.. needs to register an entry point as a Custom Element in the Custom Elements Registry. +.. needs to adapt routing so Shell registers routing happening within the module. +.. needs to adapt configuration, so services are using correct URLs to external resources. + +Below, a module setup example (Angular-based) for using the Webcomponent expose method is presented. Each file's content is going to be explained in detail, with important context information for technologies other than those presented. + +.webpack.config.js +[source, typescript] +.... +const config = withModuleFederationPlugin({ + name: 'example-ui', + filename: 'remoteEntry.js', + exposes: { + './ExampleModule': './src/main.ts' + }, + ... +}) +.... + +Webpack configuration is exposing a **main.ts** file. + +[#bootstrap-module] +.src/main.ts +[source, typescript] +.... +import('./bootstrap').catch((err) => console.error(err)) +.... + +The **main.ts** file is importing (asynchronously) the **bootstrap.ts** file. + +.src/bootstrap.ts +[source, typescript] +.... +import { bootstrapModule } from '@onecx/angular-webcomponents' +import { environment } from './environments/environment' +import { ExampleModule } from './app/module' + +bootstrapModule(ExampleModule, 'microfrontend', environment.production) +.... + +The **bootstrap.ts** file is bootstrapping the module using @onecx/angular-webcomponents library to ensure that {angular_issues_url}[Angular ngZone and platform are shared] (Angular requirement only). For other technologies, simply call any asynchronous bootstrap function required. + +[#module-bootstrapping-example] +.src/app/module.ts +[source, typescript] +.... +import { HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' +import { APP_INITIALIZER, DoBootstrap, Injector, NgModule } from '@angular/core' +import { Router, RouterModule, Routes } from '@angular/router' +import { BrowserModule } from '@angular/platform-browser' +import { BrowserAnimationsModule } from '@angular/platform-browser/animations' +import { CommonModule } from '@angular/common' +import { MissingTranslationHandler, TranslateLoader, TranslateModule } from '@ngx-translate/core' +import { + AppStateService, + ConfigurationService, + createTranslateLoader, + PortalCoreModule, + PortalMissingTranslationHandler, + PortalApiConfiguration, +} from '@onecx/portal-integration-angular' +import { AngularAuthModule } from '@onecx/angular-auth' +import { createAppEntrypoint, initializeRouter, startsWith } from '@onecx/angular-webcomponents' +import { addInitializeModuleGuard } from '@onecx/angular-integration-interface' +import { Configuration } from './shared/generated' + +@Component({ + selector: 'app-root', + template: `` +}) +export class AppEntrypointComponent {} + +export const routes: Routes = [ + { + matcher: startsWith(''), + loadChildren: () => import('./feature/feature.module').then((mod) => mod.FeatureModule) + }, + { + matcher: startsWith('tracking'), + loadChildren: () => import('./tracking/tracking.module').then((mod) => mod.TrackingModule) + } +] + +function apiConfigProvider(configService: ConfigurationService, appStateService: AppStateService) { + return new PortalApiConfiguration(Configuration, environment.apiPrefix, configService, appStateService) +} + +@NgModule({ + declarations: [AppEntrypointComponent], + imports: [ + CommonModule, + PortalCoreModule.forMicroFrontend(), + RouterModule.forRoot(addInitializeModuleGuard(routes)), + TranslateModule.forRoot({ + extend: true, + isolate: false, + loader: { + provide: TranslateLoader, + useFactory: createTranslateLoader, + deps: [HttpClient, AppStateService] + }, + missingTranslationHandler: { + provide: MissingTranslationHandler, + useClass: PortalMissingTranslationHandler + } + }), + BrowserModule, + AngularAuthModule, + BrowserAnimationsModule, + ], + exports: [], + providers: [ + { + provide: Configuration, + useFactory: apiConfigProvider, + deps: [ConfigurationService, AppStateService] + }, + { + provide: APP_INITIALIZER, + useFactory: initializeRouter, + multi: true, + deps: [Router, AppStateService] + }, + provideHttpClient(withInterceptorsFromDi()) + ] +}) +export class ExampleModule implements DoBootstrap { + constructor(private readonly injector: Injector) {} + + ngDoBootstrap(): void { + createAppEntrypoint(AppEntrypointComponent, 'example-webcomponent', this.injector) + } +} +.... + +.Navigation +[cols="1,1"] +|=== +| xref:./index.adoc[← Previous: Microfrontend Bootstrapping] +| xref:module-deep-dive.adoc[Next: Module Example Deep Dive →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/module-deep-dive.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/module-deep-dive.adoc new file mode 100644 index 000000000..517ddb403 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/module-deep-dive.adoc @@ -0,0 +1,103 @@ +:createAppEntrypoint_url: xref:../angular-webcomponents.adoc#create-app-entrypoint +:events_topic_url: xref:documentation:onecx-portal-ui-libs:libraries/integration-interface.adoc#events-topic +:initializeRouter_url: xref:../angular-webcomponents.adoc#initialize-router +:startsWith_url: xref:../angular-webcomponents.adoc#starts-with +:current_mfe_topic_url: xref:documentation:onecx-portal-ui-libs:libraries/integration-interface.adoc#current-mfe-topic +:angular-webcomponents_url: xref:../angular-webcomponents.adoc#onecx-angular-webcomponents + +[#remote-module-example-deep-dive] += Remote Module Example Deep Dive + +The **module.ts** file prepares the module for integration with the OneCX platform. + +This example showcases the recommended approach of defining modules (Angular-based) using the Webcomponent method. Here is a list of important features of this example: + +Module imports:: +* CommonModule, BrowserModule and BrowserAnimationsModule Angular modules used for adding functionality to the module. +* PortalCoreModule is defined to allow usage of OneCX components and services. +* TranslateModule is defined to allow translations using translation keys within the module. +// TODO: legacy: Add link to auth docs +// TODO: revised: There is no auth docs present in document site +* AngularAuthModule is defined to use OneCX authorization mechanisms. +* RouterModule is defined for routing to feature modules within the exposed module. + +Entrypoint component:: +AppEntrypoint is a standard Angular component that has a `` element in its template. The {createAppEntrypoint_url}[createAppEntrypoint] registers AppEntrypointComponent in the Custom Elements Registry, so anytime '' is rendered, AppEntrypointComponent should be instantiated. ++ +The third parameter, being the module's Injector, is very important. This injector will be used by the instances of AppEntrypointComponent rendered using Web Components technology, meaning that each instance will have everything related to the module already set up. That also means the `` will be using routes defined for the module. ++ +[[module-rotuer-connection]]The {createAppEntrypoint_url}[createAppEntrypoint] method is also responsible for connecting the module's router to the Shell's router. Every time the URL of the browser changes, the Shell is going to publish a new message, via {events_topic_url}[EventsTopic], with information about the new URL. The `createAppEntrypoint` method subscribes to the {events_topic_url}[EventsTopic] and updates the router state accordingly to the received information. ++ +[NOTE] +==== +For technologies other than Angular, it is recommended to: + +* register a Custom Element in the Custom Elements Registry. +* provide dependencies to registered Custom Element according to the module. +* listen to {events_topic_url}[EventsTopic] data changes and update the state of the module's routing. +==== + +Routes matching:: +Each defined route will load a feature module whenever it is activated. Because the Webcomponent expose method causes multiple routers to exist at the same time (Shell has its own router and every module or Remote Component displayed at a single point in time can have their own), an adjustment to the routes definition has to be made. ++ +The idea of routing in this example is the following: ++ +-- +* User enters 'shell_url/workspace_name/example_base_path' URL - FeatureModule is used. +* User enters 'shell_url/workspace_name/example_base_path/tracking' URL - TrackingModule is used. +-- ++ +With the following URL parts meaning: ++ +-- +* `shell_url` - the Shell Application deployment URL, e.g. `localhost:4200/shell.` +* `workspace_name` - name of the accessed Workspace, e.g. `admin`. +* `example_base_path` - base path of the example Microfrontend (configured via OneCX Core Applications), e.g. `example`. +-- ++ +Prior to routing within Microfrontend's module, the Shell uses shell_url, workspace_name and example_base_path parts of the URL to load the module. Because of this fact, the module's router needs to remove those parts from consideration when matching its routes. Usually, the `path` property of the route is used to control the route activation, but in that case, the Microfrontend's module needs a way to only match the relevant part of the URL. ++ +Using the {startsWith_url}[startsWith] function from {angular-webcomponents_url}[@onecx/angular-webcomponents] for the https://angular.dev/api/router/UrlMatcher[matcher] property of a route object results in the router considering only those URL parts relevant to the module. In order for it to work properly, the {initializeRouter_url}[initializeRouter] provider has to be added for the module as an app initializer. ++ +During module creation {initializeRouter_url}[initializeRouter]: ++ +-- +* adds Microfrontend information (based on {current_mfe_topic_url}[CurrentMfeTopic]) to each route. +* rewrites routes containing `redirectTo` for correct redirection. +* creates a new route (used when routing away from the module): +** matched when none of the defined routes were matched. +** displays nothing (for a period of time when the user routes between Microfrontends). +-- ++ +The {startsWith_url}[startsWith] method uses Microfrontend information, saved in the route's data, to remove already used parts from consideration when matching routes within the module. ++ +To create your own matchers, please consider using the {angular-webcomponents_url}[@onecx/angular-webcomponents] library. ++ +[NOTE] +==== +For technologies other than Angular, it is recommended to: + +* Use Microfrontend information from {current_mfe_topic_url}[CurrentMfeTopic] to only use relevant parts of the URL for routing and redirecting correctly. +* Ensure routing away from the module is not causing side effects. +==== + +Configuration:: +All services utilizing HttpClient used within the Microfrontend's module need to know how to make requests to external resources. Depending on the configuration of the Workspace, they need to take that context into consideration when creating a URL for those resources. ++ +A service might want to call `deployment_url/bff/search` by default. With this call being made, the MFE App will need to access the BFF. When the Application's path within the Workspace is `mfe/example` the call has to be made to `deployment_url/mfe/example/bff/search`. ++ +The `apiConfigProvider` presented in the example is utilizing the `PortalApiConfiguration` class as `Configuration` for the services. It is listening for the {current_mfe_topic_url}[CurrentMfeTopic] changes and overwriting the basePath accordingly to the received message, and all services use that information to construct a valid URL. ++ +[NOTE] +==== +For technologies other than Angular, it is recommended to: + +* Listen to {current_mfe_topic_url}[CurrentMfeTopic] changes and overwrite services configuration to ensure the correct resource is accessed. +==== + +.Navigation +[cols="1,1"] +|=== +| xref:module-bootstrapping.adoc[← Previous: Module Bootstrapping and Configuration] +| xref:index.adoc[Next: Back to Microfrontend Bootstrapping →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/overview.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/overview.adoc new file mode 100644 index 000000000..ec31046b3 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/overview.adoc @@ -0,0 +1,5 @@ +[#microfrontend-bootstrapping-overview] +== Overview +Bootstrapping a Microfrontend involves setting up the initial structure and configuration for a Microfrontend application. This process typically includes creating the necessary directories, installing dependencies, and configuring the build tools to ensure that the Microfrontend can run independently and integrate with other Microfrontends or a shell application. + +This document aims to explain the details related to Microfrontend's content bootstrapping. Depending on the content's type and expose method, there are different requirements needed to be fulfilled to ensure the content is loaded correctly by OneCX platform elements. This topic is highly related to xref:../../concepts/content-loading.adoc[Microfrontend content loading] and xref:../microfrontend-configuration.adoc[Microfrontend configuration with Webpack]. It is recommended to be familiar with those before reading this document. diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/remote-component-bootstrapping.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/remote-component-bootstrapping.adoc new file mode 100644 index 000000000..5c22289df --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/remote-component-bootstrapping.adoc @@ -0,0 +1,189 @@ +:angular_issues_url: xref:../../concepts/webcomponents/expose-content-as-webcomponent.adoc#angular_issues +:angular-webcomponents_url: xref:../angular-webcomponents.adoc#onecx-angular-webcomponents + +[#remote-component-bootstrapping-and-configuration] += Remote Component Bootstrapping and Configuration + +The following requirements need to be fulfilled when exposing Remote Components using the Webcomponent method: + +. Webpack configuration needs to expose the *main.ts* file of the Remote Component. +. The **main.ts** file of the Remote Component needs to bootstrap the component asynchronously. +. Component bootstrap +.. has to cover {angular_issues_url}[Angular issues] (for Angular-based Remote Components only). +.. needs to register the component as a Custom Element in the Custom Elements Registry. +.. needs to adapt routing so Shell registers routing happening within the Remote Component. +. Component class needs to use the Remote Component initialization mechanism. + +Below is an example of setting up a Remote Component in Angular using the Webcomponent expose method. Each file's content is going to be explained in detail, with important context information for technologies other than those presented. + +.webpack.config.js +[source, typescript] +.... +const config = withModuleFederationPlugin({ + name: 'example-ui', + filename: 'remoteEntry.js', + exposes: { + './ExampleComponent': './src/app/remotes/example/example.component.main.ts' + }, + ... +}) +.... + +Webpack configuration is exposing an **example.component.main.ts** file. + +.src/app/remotes/example/example.component.main.ts +[source, typescript] +.... +import('./example.component.bootstrap').catch((err) => console.error(err)) +.... + +[#bootstrap-remote-component] +The **example.component.main.ts** file is importing (asynchronously) the **example.component.bootstrap.ts** file. + +.src/app/remotes/example/example.component.bootstrap.ts +[source, typescript] +.... +import { + HttpClient, + provideHttpClient, + withInterceptorsFromDi, +} from '@angular/common/http'; +import { + APP_INITIALIZER, + importProvidersFrom +} from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { AngularAuthModule } from '@onecx/angular-auth'; +import { bootstrapRemoteComponent } from '@onecx/angular-webcomponents'; +import { + createRemoteComponentTranslateLoader, + UserService +} from '@onecx/portal-integration-angular'; +import { environment } from 'src/environments/environment'; +import { ExampleComponent } from './example.component'; +import { + BASE_URL, + provideTranslateServiceForRoot, +} from '@onecx/angular-remote-components'; +import { TranslateLoader } from '@ngx-translate/core'; +import { ReplaySubject } from 'rxjs'; + +function userProfileInitializer(userService: UserService) { + return async () => { + await userService.isInitialized; + }; +} + +bootstrapRemoteComponent( + ExampleComponent, + 'example-remote-component', + environment.production, + [ + provideHttpClient(withInterceptorsFromDi()), + { + provide: BASE_URL, + useValue: new ReplaySubject(1), + }, + provideTranslateServiceForRoot({ + isolate: true, + loader: { + provide: TranslateLoader, + useFactory: createRemoteComponentTranslateLoader, + deps: [HttpClient, BASE_URL], + }, + }), + importProvidersFrom( + AngularAuthModule, + BrowserModule, + BrowserAnimationsModule, + ), + { + provide: APP_INITIALIZER, + useFactory: userProfileInitializer, + deps: [UserService], + multi: true, + }, + ] +) +.... + +The **example.component.bootstrap.ts** file is bootstrapping the Remote Component using {angular-webcomponents_url}[@onecx/angular-webcomponents] library to ensure that {angular_issues_url}[Angular ngZone and platform are shared] (Angular requirement only). It also connects the Shell router with the Remote Component's router (if such exists). The last argument is an array of providers required for the component to work properly. A detailed description of this file can be found in the xref:./remote-component-deep-dive.adoc#remote-component-example-deep-dive[summary]. + +.src/app/remotes/example/example.component.ts +[source, typescript] +.... +import { CommonModule, Location } from '@angular/common'; +import { Component, Inject, Input } from '@angular/core'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { AngularAuthModule } from '@onecx/angular-auth'; +import { + UserService +} from '@onecx/angular-integration-interface'; +import { + AngularRemoteComponentsModule, + BASE_URL, + ocxRemoteComponent, + ocxRemoteWebcomponent, + RemoteComponentConfig, +} from '@onecx/angular-remote-components'; +import { + PortalCoreModule +} from '@onecx/portal-integration-angular'; +import { ReplaySubject } from 'rxjs'; +import { environment } from 'src/environments/environment' + +@NgModule({ + imports: [ + PortalCoreModule.forMicroFrontend() + ] +}) +export class SharedModule {} + +@Component({ + standalone: true, + imports: [ + AngularAuthModule, + AngularRemoteComponentsModule, + CommonModule, + SharedModule, + PortalCoreModule, + TranslateModule, + ], + selector: 'example-comp', + template: `Hello from Remote Component`, +}) +export class ExampleComponent + implements ocxRemoteComponent, ocxRemoteWebcomponent +{ + permissions: string[] = []; + + constructor( + @Inject(BASE_URL) private readonly baseUrl: ReplaySubject, + private readonly userService: UserService, + private readonly translateService: TranslateService, + private readonly exampleService: ExampleAPIService + ) { + this.translateService.use(this.userService.lang$.getValue()); + } + + @Input() set ocxRemoteComponentConfig(config: RemoteComponentConfig) { + this.ocxInitRemoteComponent(config); + } + + ocxInitRemoteComponent(config: RemoteComponentConfig): void { + this.baseUrl.next(config.baseUrl); + this.permissions = config.permissions; + this.exampleService.configuration = new Configuration({ + basePath: Location.joinWithSlash(config.baseUrl, environment.apiPrefix) + }) + } +} +.... + +.Navigation +[cols="1,1"] +|=== +| xref:./index.adoc[← Previous: Microfrontend bootstrapping] +| xref:./remote-component-deep-dive.adoc[Next: Remote Component Example Deep Dive →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/remote-component-deep-dive.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/remote-component-deep-dive.adoc new file mode 100644 index 000000000..53ff50ebc --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/remote-component-deep-dive.adoc @@ -0,0 +1,114 @@ +:angular_issues_url: xref:../../concepts/webcomponents/expose-content-as-webcomponent.adoc#angular_issues +:bootstrapRemoteComponent_url: xref:../angular-webcomponents.adoc#bootstrap-remote-component +:user_service_url: xref:documentation:onecx-portal-ui-libs:libraries/angular-integration-interface.adoc#user-service + +[#remote-component-example-deep-dive] += Remote Component Example Deep Dive + +The **example.component.ts** file prepares the Remote Component for integration with the OneCX platform. + +This example showcases the recommended approach to define Remote Components (Angular-based) using the Webcomponent method. Here is a list of important features of this example: + +Component bootstrap:: +Remote Components are better suited for integration with the Web Components Custom Elements concept. The biggest reason for this is that a Remote Component already represents a component, meaning that there is no need to define any additional entry point component (like what was done for module content type). ++ +The {bootstrapRemoteComponent_url}[bootstrapRemoteComponent] method is bootstrapping the Remote Component. It is responsible for: ++ +Creating application::: +As a first step, the {bootstrapRemoteComponent_url}[bootstrapRemoteComponent] method is going to create an Angular application. The created application will use defined providers (argument of {bootstrapRemoteComponent_url}[bootstrapRemoteComponent]). In this example, the following providers are defined: ++ +-- +* HttpClient (via provideHttpClient) - used for making HTTP calls. +* TranslateService (via provideTranslateServiceForRoot) - used for making translations via translation keys. +* providers from AngularAuthModule - OneCX authorization mechanisms. +* providers from BrowserModule. +* providers from BrowserAnimationsModule. +* APP_INITIALIZER using userProfileInitializer factory function - in ExampleComponent's constructor, the `this.userService.lang$.getValue()` call is made to set TranslationService language. Since that call is synchronous, it is important to ensure that {user_service_url}[UserService] has been initialized before fetching its data. +-- ++ +IMPORTANT: Providers passed in the {bootstrapRemoteComponent_url}bootstrapRemoteComponent method call should contain any providers required by the Remote Component. Any services or injection tokens have to be defined here. It is important that those providers are aligned with imports defined via the Remote Component's definition. Depending on the Remote Component, different providers and imports will be defined. + ++ +The created application is going to have an Injector (just like a module does). This Injector will be used by the instance of ExampleComponent rendered using Web Components technology. ++ +For Angular-based Remote Components, it is recommended to use {bootstrapRemoteComponent_url}[bootstrapRemoteComponent] and define every required provider as an argument of this method. This approach will ensure that the rendered component has all required services, tokens, etc. already set up. +Fixing {angular_issues_url}[Angular issues] (Angular requirement only)::: +The {bootstrapRemoteComponent_url}[bootstrapRemoteComponent] method takes care of ngZone and platform sharing. +Connecting router::: +The {bootstrapRemoteComponent_url}[bootstrapRemoteComponent] method is responsible for connecting the Remote Component's router to the Shell's router (if there is one defined), so their states are always the same. The connection is set up in the same way as for the <>. +Registering the Custom Element::: +The {bootstrapRemoteComponent_url}[bootstrapRemoteComponent] method registers the ExampleComponent in the Custom Elements Registry, so anytime `` is rendered, ExampleComponent should be instantiated. + ++ +[NOTE] +==== +For technologies other than Angular, it is recommended to: + +* register a Custom Element in the Custom Elements Registry. +* provide dependencies to registered Custom Element according to the Remote Component. +* listen for EventsTopic data changes and update the state of the Remote Component's routing (if routing is used). +==== + +Component definition and configuration:: +For Angular-based components, any Remote Component is required to be a standalone Angular component. The component's import array's purpose is to declare all required dependencies, just like for Angular modules. It is recommended to import: ++ +-- +* AngularAuthModule for authorization mechanisms. +* CommonModule for common Angular functionalities. +* SharedModule with `PortalCoreModule.forMicroFrontend()` import for allowing OneCX components and services usage. +* PortalCoreModule so the component recognizes OneCX components and services. +* TranslateModule for translations mechanism. +* AngularRemoteComponentsModule. +-- ++ +In the **example.component.bootstrap.ts**, some providers related to those dependencies were already declared in the {bootstrapRemoteComponent_url}[bootstrapRemoteComponent] method call. + ++ +[NOTE] +==== +For technologies other than Angular, it is recommended to: + +* define the component so that all dependencies are provided. +==== + +Configuration and initialization:: +The ExampleComponent implements two interfaces: ++ +-- +* ocxRemoteComponent - requires component to define ocxInitRemoteComponent method +* ocxRemoteWebcomponent - requires component to define ocxRemoteComponentConfig property +-- ++ +For Webcomponent method, it is required to implement ocxRemoteWebcomponent, but optional to implement ocxRemoteComponent. The `ocxRemoteComponentConfig` is set by the Remote Component's Slot Component after the Remote Component's element is created in the HTML. The value that is set is of type <>. On receiving the configuration, the Remote Component should: ++ +-- +* update BASE_URL. +* update permissions (if permissions are used). +* update the base URL of its services (if services that require external calls are used). +-- ++ +[[RemoteComponentConfig]] +.RemoteComponentConfig structure +|=== +|**Property**|**Type**|**Description** +|`appId` | `string` | Unique identifier of the Microfrontend Remote Component is part of. +|`productName` | `string` | Name of the Application currently Remote Component is part of. +|`permissions` | `string[]` | Current user permissions related to the Remote Component's Microfrontend. +|`baseUrl` | `string` | URL of Remote Component's Microfrontend to be used when accessing its content (remote entry file, assets, etc.), e.g. `'/mfe/mfe_name'`. +|=== ++ +[NOTE] +==== +For technologies other than Angular, it is recommended to: + +* implement the component so the ocxRemoteComponentConfig property is defined, and whenever it is set: +** the component's resources or the component itself will use the correct baseUrl to access external resources. +** permission checking mechanisms will use provided permissions. +==== + +.Navigation +[cols="1,1"] +|=== +| xref:remote-component-bootstrapping.adoc[← Previous: Remote Component Bootstrapping] +| xref:index.adoc[Next: Back to Microfrontend Bootstrapping →] +|=== \ No newline at end of file diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/webcomponent-expose-method.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/webcomponent-expose-method.adoc new file mode 100644 index 000000000..afd142c5e --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-bootstrapping/webcomponent-expose-method.adoc @@ -0,0 +1,18 @@ +:angular_issues_url: xref:../../concepts/webcomponents/expose-content-as-webcomponent.adoc#angular_issues +:angular-webcomponents_url: xref:../angular-webcomponents.adoc#onecx-angular-webcomponents + +[#content-exposed-using-webcomponent-method] +=== Content Exposed Using Webcomponent Method + +{angular-webcomponents_url}[Loading mechanism for modules and Remote Components exposed using Webcomponent method] requires that content is adapted to using Web Components Custom Elements. For both content types, bootstrapping logic needs to register a Custom Element in the Custom Elements Registry. + +NOTE: For Angular-based content, apart from Custom Element registration, it is also required to cover a few Angular-related issues. For more information on those issues, please refer {angular_issues_url}[here]. + +It is recommended to use the {angular-webcomponents_url}[@onecx/angular-webcomponents] library to bootstrap Microfrontend's content using its exposed methods. This library will be used in the examples throughout this document. + +.Navigation +[cols="1,1"] +|=== +| xref:angular-expose-method.adoc[← Previous: Content Exposed Using Angular Method] +| xref:./index.adoc[Next: Back to Microfrontend Bootstrapping →] +|=== diff --git a/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-configuration.adoc b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-configuration.adoc new file mode 100644 index 000000000..5b91b34d3 --- /dev/null +++ b/docs/modules/onecx-docs-overview/pages/module-federation - v2/onecx/microfrontend-configuration.adoc @@ -0,0 +1,124 @@ +:imagesdir: ../../images +:idprefix: +:idseparator: - + += Configure Microfrontend to use Module Federation +This section describes how to configure a microfrontend to use *Module Federation* for loading and dependency sharing in OneCX. + +This guide uses *webpack* for the examples, but you can use any other tool that supports *Module Federation*. + +Following are the *checkpoints* to set up a microfrontend with *Module Federation*: + +== Exposed content + +Each Microfrontend can expose multiple modules and Remote Components. Every separate module and Remote Component needs to be defined as a separate, unique entry representing a remote module. Each entry is a Key-Value Pair: + + - *Key* - Name of the exposed module. + - *Value* - File to be used for module bootstrap. + +As we use webpack for *Module Federation* configuration, the following changes are made in the `webpack.config.js` file of the microfrontend: + +.Example - Expose *Module* or *Remote Component* + +[source, javascript] +---- +const { withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack') +const config = withModuleFederationPlugin({ + // other configuration + exposes: { + './ExampleModule': './src/main.ts', + './ExampleComponent': './src/remotes/example/example.component.main.ts' + } + // other configuration +}) +---- + +== Shared dependencies + +In OneCX, we recommend sharing all dependencies to take full advantage of *Module Federation* capabilities. + + - share all *@onecx* packages + - share *rxjs* + +For *Angular Applications*: + + - share all *@angular* packages (make sure to not share as *singleton*) + - share *primeng* + - share *@ngx-translate/core* + +.Example - Share relevant dependencies +[%collapsible] +==== +[source, javascript] +---- +const { withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack') +const config = withModuleFederationPlugin({ + // other configuration + shared: share({ + /*All Angular packages */ + '@angular/core': { requiredVersion: 'auto', includeSecondaries: true }, + '@angular/forms': { requiredVersion: 'auto', includeSecondaries: true }, + '@angular/common': { requiredVersion: 'auto', includeSecondaries: { skip: ['@angular/common/http/testing'] } }, + '@angular/common/http': { requiredVersion: 'auto', includeSecondaries: true }, + '@angular/platform-browser': { requiredVersion: 'auto', includeSecondaries: true }, + '@angular/router': { requiredVersion: 'auto', includeSecondaries: true }, + + /*All @OneCX, primeNg, rxjs and translation packages */ + '@ngx-translate/core': { requiredVersion: 'auto' }, + primeng: { requiredVersion: 'auto', includeSecondaries: true }, + rxjs: { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/accelerator': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/angular-accelerator': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/angular-auth': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/angular-integration-interface': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/angular-remote-components': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/angular-testing': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/angular-webcomponents': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/integration-interface': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/keycloak-auth': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/ngrx-accelerator': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/portal-integration-angular': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/portal-layout-styles': { requiredVersion: 'auto', includeSecondaries: true } + }), + // other configuration +}) +---- +==== + +== Shared Mapping Property +The shared mapping should be empty. + +.Example - Empty Shared Mapping +[source, javascript] +---- +const { withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack') +const config = withModuleFederationPlugin({ + // other configuration + sharedMappings: [] + // other configuration +}) +---- + +== Remote entry file name and Remote name + +* *Remote File* - The name of the remote entry file (usually `remoteEntry.js`) +* *Remote Name* - The unique name of the Microfrontend + +.Example - Remote file and name + +[source, javascript] +---- +const { withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack') +const config = withModuleFederationPlugin({ + // other configuration + name: 'example-ui', + filename: 'remoteEntry.js', + // other configuration +}) +---- + +.Navigation +[cols="1"] +|=== +| xref:./index.adoc[← Back to Module federation bootstrapping and configuration in OneCX] +|=== \ No newline at end of file