Micro Frontends
From Concept To Practice



On Schedule
- Why do we need it?
- What is it?
- Available technologies
- Common Approaches
- Our solution
- Demo



Front ends are getting bigger
Amplify Dashboard
- Reports
- Campaign settings
- Conversions
- Segments
- Payments
- Video





- Encapsulation css/js
- Performance
- Team Ownership
- Future Proof
- Sharing Basics
- Moduler
- Communication
- Seamless UI/UX
- Easy to Implement
Off The Shelf Solutions?

Partial Solutions

Good old Iframes

Encapsulation css/js
Performance
Team Ownership
Future Proof
Sharing Basics
Moduler
Communication
Seamless UX
Easy to Implement
Build Composition
NPM/MonoRepo




Encapsulation css/js
Performance
Team Ownership
Future Proof
Sharing Basics
Moduler
Communication
Seamless UX
Easy to Implement
Run time Composition




Encapsulation css/js
Performance
Team Ownership
Future Proof
Sharing Basics
Moduler
Communication
Seamless UX
Easy to Implement

Our Solution
Runtime composition
Forgo multi frameworks for now
A little help from Angular...

Dont rely on third party tools
use webpack for encapsulation

Angular Modules
import {NgModule} from '@angular/core'
import {CommonModule} from '@angular/common'
@NgModule({
imports: [CommonModule],
declarations: [
MyComponent,
MyComponent2
],
providers: [
MyService
],
exports: [
MyComponent2
]
})
export class MyApp {}Provide Encapsulation
Can Expose Component Out
Can run as independent app or imported to container app
Have own routing

const routes: Routes = [
{
path: 'customers',
loadChildren: './customers/customers.module#CustomersModule'
},
{
path: 'orders',
loadChildren: './orders/orders.module#OrdersModule'
}import {Compiler, ModuleWithComponentFactories, NgModuleRef} from '@angular/core'
export class ContactsModuleLoader {
constructor(private compiler: Compiler) {
}
loadContacts() {
import('./contacts/contacts.module').then(this.compileModule.bind(this));
}
compileModule(module: NgModuleRef<any>){
this.compiler.compileModuleAndAllComponentsAsync(module)
.then((moduleWithFactories: ModuleWithComponentFactories<any>) => {
console.log('contacts are alive!')
})
}
}Lazy Loading
Dynamic Loading


This only works at build time
Webpack-Share-Loader
var core_1 = __webpack_require__(19);
var ExtComponent = /** @class */ (function () {
function ExtComponent() {
}
ExtComponent = __decorate([
core_1.Component({})
])
import {Component} from '@angular/core';
@Component({}) rules: [{
test: /\.js?$/,
use: [{
loader: 'share-loader',
options: {
modules: [/@angular/, /@uirouter\/angular/],
namespace: 'container-app'
}
}]
}]Share-loader
Container App webpack.config.js
Output:
(function(global) {if(!global["container-app"]) global["container-app"] = {};
if(!global["container-app"]["angular"]) global["container-app"]["angular"] = {};
module.exports = global["container-app"]["angular"]["core"] =
Object.assign(global["container-app"]["angular"]["core"] || {}, __webpack_require__(231));
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(15))) externals: [
Externals({
namespace: 'container-app',
modules: [/@angular/, /@uirouter\/angular/]
})
],
output: {
library: 'childapp',
libraryTarget: 'umd'
}, "object" == typeof exports && "object" == typeof module
? module.exports = e(require("@angular/common"))
: "function" == typeof define && define.amd
? define(["@angular/common"], e)
: "object" == typeof exports
? exports.videoApp = e(require("@angular/common"))
: t.videoApp = e(t["container-app"].angular.common)Share-loader
Child App webpack.config.js
Output:

Module
Container app
Reports team
Module
Module
Webpack build
Share-loader
Payments team
Contanier app






Module bundle
Independent deployment



Independent service



Reports team

{ }
Payments team
Container app


At runtime all modules share common resources via a common namespace
Request URL: https://my.outbrain.com/videocampaignscreation/api/external
ResponseBody:
{
appName: "videoApp"
file: "static/external/vidapp.f1a32d630b33f7ffe64e.external.js"
moduleName: "AppModule"
}

Inter app communication
Container app
App1
App2
App3



Event Bus Instance



Questions?

MicroFrontEnds
By Maor Frankel
MicroFrontEnds
- 702
