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?
Copy of Micro Fronends
By Maor Frankel
Copy of Micro Fronends
- 454