@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