You are on page 1of 73

@BASTAcon & @ManfredSteyer

Typical Module Structure

AppModule … SharedModule
SharedModule

Root Module Feature Modules Shared Modules

Page ▪ 3 @ManfredSteyer
Contents
• (npm-)Packages
• Nx Monorepos
• Strategic Design and DDD
• Microfrontends

@ManfredSteyer
Manfred Steyer

@ManfredSteyer
Monorepos

@ManfredSteyer
Monorepo
Structure

@ManfredSteyer
Advantages

Everyone uses the latest versions

No version conflicts

No burden with distributing libs

@ManfredSteyer
Tooling & Generator
https://nrwl.io/nx

@ManfredSteyer
Visualize
Module
Structure

@ManfredSteyer
Creating a Workspace
npm install -g @angular/cli

ng new workspace

cd workspace

ng generate app my-app


ng generate lib my-lib

ng serve --project my-app


ng build --project my-app

@ManfredSteyer
Creating a Workspace
npm install -g @angular/cli

npm init nx-workspace workspace

cd workspace

ng generate app my-app


ng generate lib my-lib

ng serve --project my-app


ng build --project my-app

@ManfredSteyer
DEMO

@ManfredSteyer
DDD
in a nutshell

@ManfredSteyer
Methodology for
bridging the gap b/w
requirements and
architecture/ design

@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
Domain Driven Design
Design Patterns
Decomposing a System
& Practices

Strategic Design Tactical Design


@ManfredSteyer
Domain Driven Design
Design Patterns
Decomposing a System
& Practices

Strategic Design Tactical Design


@ManfredSteyer
@ManfredSteyer
Example

Flight System

@ManfredSteyer
Example

Booking Check-in

Sub-Domains
Luggage Boarding

@ManfredSteyer
Finding Sub-Domains

Travel Agency Check-in Agent Boarding Agent


Passenger

Book Check-in Check-in Board Pickup


Flight Passenger Luggage Plane Luggage

@ManfredSteyer
Booking Boarding

Flight
Flight Ticket

Price

Seats Ubiquitous Language

Tickets Bounded Context

Passenger

@ManfredSteyer
Context Map

Boarding Booking Luggage

Check-in

@ManfredSteyer
Shared Kernel (if really needed) & other libs

Smart
Comp. Booking Boarding Shared

Dumb Comp.
Feature Feature Feature Feature Feature

UI UI UI UI UI UI UI UI UI

Domain Domain Domain Domain Domain Domain

Util Util Util Util Util Util

@ManfredSteyer Enterprise Monorepo Patterns, Nrwl 2018: https://tinyurl.com/y2jjxld7


@ManfredSteyer
DEMO

@ManfredSteyer
@ManfredSteyer
Finegrained Libraries
• Unit of recompilation
• Unit of retesting
• Access restrictions
• Information Hiding
• Easy: Just ng g lib …
• Future replacement for
NgModules?

@ManfredSteyer
Micro
Frontends?
Short outlook

@ManfredSteyer
Microfrontends

Booking App Check-in App

Luggage App Boarding App

@ManfredSteyer
@ManfredSteyer
Deployment Monolith

Booking Boarding Shared

Flight App

Feature Feature Feature Feature Feature

… … … … … … … … …

@ManfredSteyer @ManfredSteyer
Microfrontends

Booking Boarding Shared

Booking App Boarding App

Feature Feature Feature Feature Feature

… … … … … … … … …

@ManfredSteyer
Option 1: One App per Domain

Booking Boarding Shared

Booking App Boarding App

Feature Feature Feature Feature Feature

… … … … … … … … …

Monorepo
@ManfredSteyer
Option 2: One Monorepo per Domain

Booking Boarding Shared


Publish shared libs
Booking App Boarding App seperately via npm

Feature Feature Feature Feature Feature

… … … … … … … … …

Repository 1 Repository 2
@ManfredSteyer Repository n
Benefits
Autonomous Teams

Separate Development

Separate Deployment

Own architecture decisions

Own technology descisions

@ManfredSteyer
Integration via
Hyperlinks

@ManfredSteyer
UI Composition
w/ Hyperlinks

µApp µApp µApp


SPA SPA SPA

@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
Integration via
Shell

@ManfredSteyer
Providing a (SPA based) Shell

Shell

µApp µService
µApp µApp

@ManfredSteyer
@ManfredSteyer
Idea
Does not work with
webpack/ Angular CLI

const Component = import('http://other-app/xyz')

Even lazy parts must be


known at compile time!

@ManfredSteyer
Webpack 5 Module Federation

Shell (Host) Microfrontend (Remote)

import('mfe1/Cmp')

// Maps Urls in // Expose files in


// webpack config // webpack config
remotes: { exposes: {
mfe1: "http://..." Cmp: './my.cmp.ts'
} }

@ManfredSteyer
How to Get the Microfrontend's URL?

Shell (Host) Microfrontend (Remote)

<script src="…"></script> RemoteEntrypoint.js

@ManfredSteyer
How to Share Libs?

Shell (Host) Microfrontend (Remote)

shared: [ shared: [
"@angular/core", "…" "@angular/core", "…"
] ]

@ManfredSteyer
@ManfredSteyer
Default Behavior
Selecting the highest compatible version

10.0 10.1

@ManfredSteyer
Default Behavior
Conflict: No highest compatible version

11.0 10.1

@ManfredSteyer
Example
• Shell: my-lib: ^10.0
• MFE1: my-lib: ^10.1
• MFE2: my-lib: ^9.0
• MFE3: my-lib: ^9.1

Result:
• Shell and MFE1 share ^10.1
• MFE2 and MFE3 share ^9.1

@ManfredSteyer
Configuring Singletons
shared: {
"my-lib": {
singleton: true
}
}

11.0 10.1

@ManfredSteyer
Configuring Singletons
shared: {
"my-lib": {
singleton: true,
strictVersion: true // Error instead of warning!
}
}

11.0 10.1

@ManfredSteyer
Relaxing Version Requirements
shared: {
"my-lib": {
requiredVersion: ">=1.0.1 <11.1.1"
}
}

@ManfredSteyer
@ManfredSteyer
?

@ManfredSteyer
Custom Builder

@ManfredSteyer
@ManfredSteyer
1) ng add @angular-architects/module-federation
2) Adjust generated configuration
3) ng serve

@ManfredSteyer
1) npm i @angular-architects/module-federation -D
2) ng g @angular-architects/module-federation:init
3) Adjust generated configuration
4) ng serve

@ManfredSteyer
@ManfredSteyer
@ManfredSteyer
Wrap them into Web Components

Angular App React App


(MFE) (MFE)

@ManfredSteyer
@ManfredSteyer
await import('other-app/web-cmp');

@ManfredSteyer
const rootElm = document.createElement('web-cmp')
document.body.appendChild(rootElm);

await import('other-app/web-cmp');

@ManfredSteyer
WrapperComponent
const rootElm = document.createElement('web-cmp')
document.body.appendChild(rootElm);

await import('other-app/web-cmp');

@ManfredSteyer
@ManfredSteyer
https://red-ocean-0fe4c4610.azurestaticapps.net

@ManfredSteyer
Challanges
• Bundle Size
• Multiple Routers
• Bootstrapping Several Angular Instances
• Share Platform-Object when same version is reused
• Share ngZone

@ManfredSteyer
@ManfredSteyer
Choosing a Solution

@ManfredSteyer
Some General Advice

Module Federation
little
Hyperlinks
Shared state,
navigation b/w yes iframes
apps Legacy Apps or
yes Load Bundles on
*very very* strong
much Demand
isolation? Separate
no Deployment/ mix
Technologies?
no Monolith

@ManfredSteyer

You might also like