Slide 1

Slide 1 text

Micro Frontends Michael Egger-Zikes with Angular & Module Federation ANGULARarchitects.io

Slide 2

Slide 2 text

Architecture: Micro Frontends Module Federation Synchronize Routers What this talk is about Single Version Multi Version Michael Egger-Zikes (@MikeZks)

Slide 3

Slide 3 text

About Michael • Michael Egger-Zikes ANGULARarchitects.io • Trainings, Consultancy, Reviews • Conference Speaker • Focus on Angular Remote Workshops: Public & tailored to your company angulararchitects.io/angular-workshops Michael Egger-Zikes (@MikeZks)

Slide 4

Slide 4 text

Micro Frontends Michael Egger-Zikes (@MikeZks) Booking App Check-in App Boarding App Luggage App

Slide 5

Slide 5 text

Micro Frontends are first and foremost about scaling teams!

Slide 6

Slide 6 text

Build Monolith Michael Egger-Zikes (@MikeZks) Booking Boarding Shared Feature Feature Feature Feature Feature … … … … … … … … … Flight App

Slide 7

Slide 7 text

DEMO Build Monolith

Slide 8

Slide 8 text

Micro Frontends Michael Egger-Zikes (@MikeZks) Booking Boarding Shared Feature Feature Feature Feature Feature … … … … … … … … … Booking App Boarding App

Slide 9

Slide 9 text

Option 1: One App per Domain Booking Boarding Shared Feature Feature Feature Feature Feature … … … … … … … … … Booking App Boarding App Monorepo

Slide 10

Slide 10 text

Option 2: One Monorepo per Domain Booking Boarding Shared Feature Feature Feature Feature Feature … … … … … … … … … Booking App Boarding App Publish shared libs seperately via npm Repository 2 Repository 1 Repository n

Slide 11

Slide 11 text

Benefits Michael Egger-Zikes (@MikeZks) Autonomous Teams Separate Development Separate Deployment Own architecture decisions Own technology decisions

Slide 12

Slide 12 text

Micro Frontend Integration via Shell

Slide 13

Slide 13 text

Providing a (SPA based) Shell Michael Egger-Zikes (@MikeZks) µService µApp µApp µApp Shell

Slide 14

Slide 14 text

Webpack 5 Module Federation

Slide 15

Slide 15 text

Idea Michael Egger-Zikes (@MikeZks) const Component = import('http://other-app/xyz') Does not work with webpack/ Angular CLI Even lazy parts must be known at compile time!

Slide 16

Slide 16 text

Webpack 5 Module Federation Michael Egger-Zikes (@MikeZks) Shell (Host) Micro Frontend (Remote) // Maps Urls in // webpack config remotes: { mfe1: 'http://...' } // Expose files in // webpack config exposes: { Cmp: './my.cmp.ts' } import('mfe1/Cmp')

Slide 17

Slide 17 text

How to Get the Micro Frontend's URL? Michael Egger-Zikes (@MikeZks) Shell (Host) Micro Frontend (Remote) remoteEntry.js

Slide 18

Slide 18 text

How to Share Libs? Michael Egger-Zikes (@MikeZks) Shell (Host) Micro Frontend (Remote) shared: { '@angular/core': { … } } shared: { '@angular/core': { … } }

Slide 19

Slide 19 text

Dealing with Version Mismatches

Slide 20

Slide 20 text

Default Behavior Michael Egger-Zikes (@MikeZks) Selecting the highest compatible version 10.0 10.1

Slide 21

Slide 21 text

Default Behavior Michael Egger-Zikes (@MikeZks) Conflict: No highest compatible version 11.0 10.1

Slide 22

Slide 22 text

Configuring Singletons Michael Egger-Zikes (@MikeZks) shared: { 'my-lib': { singleton: true } } 11.0 10.1

Slide 23

Slide 23 text

Configuring Singletons Michael Egger-Zikes (@MikeZks) shared: { 'my-lib': { singleton: true, strictVersion: true // Error instead of warning! } } 11.0 10.1

Slide 24

Slide 24 text

Relaxing Version Requirements Michael Egger-Zikes (@MikeZks) shared: { 'my-lib': { requiredVersion: '>=1.0.1 <11.1.1' } }

Slide 25

Slide 25 text

Federated Angular: Angular, CLI & Module Federation

Slide 26

Slide 26 text

Webpack 5 Angular CLI Module Federation Configuration ?

Slide 27

Slide 27 text

webpack Angular CLI Module Federation Configuration Custom Builder

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

Usage Michael Egger-Zikes (@MikeZks) • Generate Module Federation config • Adjust generated configuration • webpack.config.js • Restart Dev-Server ng add @angular-architects/module-federation --project shell --port 4200 --type dynamic-host ng serve shell

Slide 30

Slide 30 text

DEMO Module Federation – Single Version

Slide 31

Slide 31 text

Multi Framework / Version Solutions

Slide 32

Slide 32 text

Abstracting Differences b/w SPA Frameworks Michael Egger-Zikes (@MikeZks) Wrap them into Web Components Angular App (MFE) React App (MFE) Corse-grained Web Component

Slide 33

Slide 33 text

Loading Web Components via Module Federation

Slide 34

Slide 34 text

Module Federation: Bootstrap App Michael Egger-Zikes (@MikeZks) const main = await import('other-app/main'); main.bootstrap();

Slide 35

Slide 35 text

Module Federation: Bootstrap App Michael Egger-Zikes (@MikeZks) const main = await import('other-app/main'); main.bootstrap(); const rootElm = document.createElement('app-root') document.body.appendChild(rootElm);

Slide 36

Slide 36 text

Module Federation: Bootstrap App Michael Egger-Zikes (@MikeZks) await import('other-app/main'); // Self-Bootstrapping const rootElm = document.createElement('app-root') document.body.appendChild(rootElm);

Slide 37

Slide 37 text

Routing to Another SPA? Michael Egger-Zikes (@MikeZks) await import('other-app/main'); const rootElm = document.createElement('app-root') document.body.appendChild(rootElm); WrapperComponent

Slide 38

Slide 38 text

Resulting Architecture Michael Egger-Zikes (@MikeZks)

Slide 39

Slide 39 text

Challenges Michael Egger-Zikes (@MikeZks) • Bundle Size • Multiple Routers • Bootstrapping several Angular instances • Share Platform-Object when same version is reused • Share ngZone

Slide 40

Slide 40 text

Challenges & Solutions Michael Egger-Zikes (@MikeZks)

Slide 41

Slide 41 text

5 Steps to Multi Framework / Version

Slide 42

Slide 42 text

Step #1: Expose MFE via Web Components Michael Egger-Zikes (@MikeZks) ng add @angular/elements

Slide 43

Slide 43 text

Step #1: Expose MFE via Web Components Michael Egger-Zikes (@MikeZks) @NgModule({ imports: [BrowserModule], declarations: [AppComponent], bootstrap: [] }) export class AppModule { }

Slide 44

Slide 44 text

Step #1: Expose MFE via Web Components Michael Egger-Zikes (@MikeZks) @NgModule({ imports: [BrowserModule], declarations: [AppComponent], bootstrap: [] }) export class AppModule { constructor(private injector: Injector) { } }

Slide 45

Slide 45 text

Step #1: Expose MFE via Web Components Michael Egger-Zikes (@MikeZks) @NgModule({ imports: [BrowserModule], declarations: [AppComponent], bootstrap: [] }) export class AppModule { constructor(private injector: Injector) { } ngDoBootstrap() { const AngularAppRoot = createCustomElement( AppComponent, { injector: this.injector }); customElements.define('angular-element', AngularAppRoot); } }

Slide 46

Slide 46 text

Step #1: Expose MFE via Web Components Michael Egger-Zikes (@MikeZks) Result: Browser renders component w/o framework support

Slide 47

Slide 47 text

Step #2: Expose MFE via Module Federation Michael Egger-Zikes (@MikeZks) // webpack.config.js in Micro Frontend plugins: [ new ModuleFederationPlugin({ name: 'angularApp', filename: 'remoteEntry.js', exposes: { './rootapp': './projects/mfe/src/bootstrap.ts', }, shared: { '@angular/core': { 'requiredVersion: auto' }, '@angular/common': { 'requiredVersion: auto' }, '@angular/router': { 'requiredVersion: auto' }, 'rxjs': { 'requiredVersion: auto' } } }) ]

Slide 48

Slide 48 text

Step #3: Use Bootstrap Helper in MFE Michael Egger-Zikes (@MikeZks) // Bootstrapping in both, Shell and Micro Frontends bootstrap(AppModule, { production: environment.production, appType: 'microfrontend'; });

Slide 49

Slide 49 text

Step #3: Use Bootstrap Helper in Shell Michael Egger-Zikes (@MikeZks) // Bootstrapping in both, Shell and Micro Frontends bootstrap(AppModule, { production: environment.production, appType: 'shell'; });

Slide 50

Slide 50 text

How does Routing work in a Multi Framework and Multi Version setup? ?

Slide 51

Slide 51 text

Step #4: Make Shell to Route to MFE Michael Egger-Zikes (@MikeZks) { path: 'multi-version', component: WebComponentWrapper, data: { type: 'module', remoteEntry: 'https://[…]/remoteEntry.js', remoteName: 'angularApp', exposedModule: './rootapp', elementName: 'angular-element‘ } as WebComponentWrapperOptions }

Slide 52

Slide 52 text

DEMO Module Federation – Multi Version

Slide 53

Slide 53 text

Routing facts • Several bootstrapped apps → different Router instances • Only one address bar → only one URL • Default behavior →URL gets overwritten w/o coordination • Sounds like chaos, right? Michael Egger-Zikes (@MikeZks)

Slide 54

Slide 54 text

URL Composition • Single App URLs: • Use the concept of Angular’s named RouterOutlets → But with different Apps and multiple Routers https://www.angulararchitects.io/mfe-1/article/search https://www.angulararchitects.io/mfe-2/invoice/edit/8 https://www.angulararchitects.io/(mfe-1:article/search//mfe-2:invoice/edit/8) Michael Egger-Zikes (@MikeZks)

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

Step #5: Synchronize Routers (beta) Michael Egger-Zikes (@MikeZks) @NgModule({ imports: [ BrowserModule, AppRoutingModule, MicroAppRoutingModule.forShell({ name: 'shell' }) ], … }) export class AppModule { }

Slide 57

Slide 57 text

Step #5: Synchronize Routers (beta) Michael Egger-Zikes (@MikeZks) @NgModule({ imports: [ BrowserModule, AppRoutingModule, MicroAppRoutingModule.forMicroApp({ name: 'mfe' }) ], … }) export class AppModule { }

Slide 58

Slide 58 text

DEMO Synchronize Routers

Slide 59

Slide 59 text

! • Define your architecture targets • Decide between • Build Monolith • MF Single Version • MF Multi Version • Decide whether you need to show more than one Micro App at one time Key takeaways

Slide 60

Slide 60 text

[web] ANGULARarchitects.io [twitter] Michael Egger-Zikes (@MikeZks) [npm] @angular-architects/module-federation @angular-architects/module-federation-tools @angular-architects/microapp [repo] https://github.com/mikezks/mfe-monorepo Contact | Libs | Source Remote Workshops: Public & tailored to your company angulararchitects.io/angular-workshops