-
Notifications
You must be signed in to change notification settings - Fork 10
docs: module federation onecx section #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| [#onecx-angular-webcomponents] | ||
| == @onecx/angular-webcomponents Details | ||
| Using <<onecx/angular-webcomponents, @onecx/angular-webcomponents>> 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. | ||
|
|
||
| // TODO: Link to example in guide | ||
| [#bootstrapmodule] | ||
| === bootstrapModule Function | ||
| 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<M> | ||
| |Angular Module to load | ||
|
|
||
| |appType | ||
| |'shell' or 'microfrontend' | ||
| |Use 'microfrontend' for exposing modules | ||
|
|
||
| |production | ||
| |boolean | ||
| |if application should run in production mode | ||
| |=== | ||
|
|
||
| // TODO: Link to example in guide | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why TODO comment?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. from legacy docs. addressed in this PR - #55 |
||
| [#bootstrap-remote-component] | ||
| === bootstrapRemoteComponent Function | ||
| 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<any> | ||
| |Angular Component to load | ||
|
|
||
| |elementName | ||
| |string | ||
| |HTML element name to be used for Custom Elements registration | ||
|
|
||
| |production | ||
| |boolean | ||
| |if application should run in production mode | ||
|
|
||
| |providers | ||
| |Array<(Provider \| EnvironmentProviders)> | ||
| |Array of providers for Remote Component to run | ||
| |=== | ||
|
|
||
| // TODO: Link to example in guide | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why todo comment?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. from legacy docs. addressed in this PR - #55 |
||
| [#create-app-entrypoint] | ||
| === createAppEntrypoint Function | ||
| 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<any> | ||
| |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 ... | ||
|
|
||
| // TODO: Link to example in guide | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why todo comment?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. from legacy docs. addressed in this PR - #55 |
||
| [#starts-with] | ||
| === startsWith Function | ||
| 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. | ||
| |=== | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| [#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)); | ||
| .... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| [#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:./webpack.adoc[Webpack configuration]. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please check if the xref is accessible, when all PRs are merged |
||
|
|
||
| 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] | ||
|
Comment on lines
+7
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please check if the xref is accessible, when all PRs are merged |
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please check the xrefs if they are correctly linked, when all PRs are merged |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Todo correct new links | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why TODO comment?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. from legacy docs. addressed in this PR - #55 |
||
| :mfe-loading_url: xref:../microfrontend-content-loading.adoc | ||
| :angular-webcomponents_url: xref:../webcomponents.adoc#onecx-angular-webcomponents | ||
| :angular_issues_url: xref:../webcomponents.adoc#angular-issues | ||
| :createAppEntrypoint_url: xref:../webcomponents.adoc#create-app-entrypoint | ||
| :startsWith_url: xref:../webcomponents.adoc#starts-with | ||
| :bootstrapRemoteComponent_url: xref:../webcomponents.adoc#bootstrap-remote-component | ||
| :initializeRouter_url: xref:../webcomponents.adoc#initialize-router | ||
| :events_topic_url: xref:documentation:onecx-portal-ui-libs:libraries/integration-interface.adoc#events-topic | ||
| :current_mfe_topic_url: xref:documentation:onecx-portal-ui-libs:libraries/integration-interface.adoc#current-mfe-topic | ||
| :user_service_url: xref:documentation:onecx-portal-ui-libs:libraries/angular-integration-interface.adoc#user-service | ||
|
|
||
| [#microfrontend-bootstrapping] | ||
| = Microfrontend Bootstrapping | ||
|
|
||
| include::./overview.adoc[] | ||
|
|
||
| == Key concepts | ||
|
|
||
| * xref:bootstrapping-explained.adoc[Microfrontend Content Bootstrapping Explained] | ||
|
|
||
| == Module | ||
|
|
||
| * xref:module-bootstrapping.adoc[Module Bootstrapping and Configuration] | ||
| * xref:module-deep-dive.adoc[Remote Module Example Deep Dive] | ||
|
|
||
| == Remote Component | ||
|
|
||
| * xref:remote-component-bootstrapping.adoc[Remote Component Bootstrapping and Configuration] | ||
| * xref:remote-component-deep-dive.adoc[Remote Component Example Deep Dive] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| 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. | ||
|
|
||
| .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. | ||
|
|
||
| .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: `<router-outlet></router-outlet>` | ||
| }) | ||
| 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) | ||
| } | ||
| } | ||
| .... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why TODO comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from legacy docs. addressed in this PR - #55