Microservices in frontend: architectures and solutions Mikhail Kuznetcov, ING
Mikhail Kuznetcov Dev engineer at ING Twitter: @legkoletat Github: github.com/shershen08 Agenda
Agenda ● Microservices ● Modern frontend ● Microservice-oriented frontend solutions ● Challenges and conclusion
Microservices
Microservices ● Single responsibility principle - “granularity” ● Faster developers onboarding ● Faster adding features ● Ease of deployment* ● Freedom to choose technology* ● High scalability
Modern frontend
● Complexity ● Size (100s of files, 100s of KLOC) ● Size of the teams (10s developers) ● Technological diversity ● Constant upgrades and migrations
History 2010 BigPipe by Facebook 2016 Micro-frontends.org Mosaic project 2017 Adoption of Web components
2019 thoughtworks.com/radar/te chniques/micro-frontends
Architectures FRONTEND BACKEND App1 App2 App3 Infra (BE4FE, NGNIX, etc) MS1 MS2 MS3 MS5 MS4 MS6 FRONTEND + BACKEND
Solutions
Solutions overview ● In-browser: single-spa ● Server-side: tailor ● iFrames & per-route apps ● Web components as wrapper
In-browser: Single-spa github.com/CanopyTax/single-spa ● In browser ● Lazy load ● Parts of one page & separate routes ● Share styles, utils, data, events etc. ● Unified lifecycle @legkoletat | Microservices in frontend: architectures and solutions
Schema #1: Single-spa Widget app 1 Widget app 2 Dashboard app Single-spa + config Header app index.html
Single-spa: root config //single-spa-config.js import {declareChildApplication, start} from 'single-spa'; declareChildApplication('app-user-profile', () => import('PATH_TO/app.user.profile.js'),pathPrefix('/profile’)); declareChildApplication('app-transactions', () => import('PATH_TO/app.transactions.js'),pathPrefix('/transactions’)); //etc start();
Single-spa: configure app // app-user-profile.js export function bootstrap(props) { return Promise .resolve() .then(() => { // one-time app initialization code }); } //mount callback //unmount callback
Stitching fragments github.com/zalando/tailor ● Backend powered (NodeJS) ● Serves parts of one page ● Provides complete toolset - Mosaic
Widget app 1 Schema #2: Tailor github.com/shershen08/tailor-vue-demo Widget app 2 Dashboard app Tailor + Webserver Header app HTML-like template @legkoletat | Microservices in frontend: architectures and solutions
Tailor server const Tailor = require('node-tailor'); const tailor = new Tailor({ templatesPath: '/built-apps-folder' }); const server = http.createServer((req, res) => { // custom server logic tailor.requestHandler(req, res) }) server.listen(process.env.PORT);
Tailor template <body> <!-- header --> <div id="header"> <span class="fragment-error">Header failed to load</span> </div> <fragment src="https://abs123.company.internal.com"></fragment> <!-- dashboard --> <fragment src="https://dashb22.company.internal.com" primary> </fragment>
Tailor app setup "scripts": { "start": "npm run start-fragments & node tailor.js", "install-fragment-dependencies": "lerna bootstrap", "build-fragments": "lerna run build", "start-fragments": "lerna run --parallel start", "watch-fragments": "lerna run --parallel dev" }, App1 app1.min.js assets/ Serve to tailor Single repo per app: Or in monorepo: Pipeline
Single app per route ● Easy to setup ● No direct interaction ● Transfer state ● Control styles Image from Elisabeth Engel: Break Up With Your Frontend Monolith
iFrames ● Security ● Content adjustment - size, scroll ● Data exchange (via postMessage) ● Control styles //app 1 window.addEventListener("message", receiveMessage, false); //app 2 window.postMessage("hello there!", "http://example.com");
Widget app 1 Schema #3: App per route & iframe Widget app 2 Dashboard app Header app Separate repos, pipelines, etc Header No SPA State: via server or request params
Framework + Web components ● WCs in 2019 are widespread and supported ● DOM & styles can be isolated ● From apps to single components
Framework + Web components github.com/vuejs/vue-web-component-wrapper Example for Vue, same can be for Angular, React, Svelte, etc
Glimpse of future: Portals <portal id="myPortal" src="https://www.example.com/"></portal> github.com/WICG/ Secure and seamless navigation Portal can be activated myPortal.activate({ data: [...] }); Other document (portal) listens to activation, loads data and react window.addEventListener('portalactivate', e => { let predecessor = e.adoptPredecessor(document); //etc
Challenges & conclusions
Technical challenges ● More complex setup ● Managing state and passing data & events ● Predictable and reusable styles ● Page code size (TTI, loading, debugging) var bus = new EventBus(); bus.on('someEvent', function (data) { console.log('got ' + data); }); bus.on('someEvent', function foo () { bus.off('someEvent', foo); });
Non-technical challenges ● Onboarding new developers ● Team composition ● Knowledge transfer ● More moving parts (compatibility, upgrades)
Pros Single Responsibility Principle Fast onboarding and adding features Ease of testing, deployment Freedom to choose technology @legkoletat | Microservices in frontend: architectures and solutions
Do you really need this? 1. Business profile 2. Application usage profile 3. Size of codebase 4. Infrastructure 5. Size, stablity and maturity of team
Thank you! Questions? Presentation PDF on Slideshare

Front end microservices: architectures and solution

  • 1.
    Microservices in frontend: architecturesand solutions Mikhail Kuznetcov, ING
  • 2.
    Mikhail Kuznetcov Dev engineerat ING Twitter: @legkoletat Github: github.com/shershen08 Agenda
  • 3.
    Agenda ● Microservices ● Modernfrontend ● Microservice-oriented frontend solutions ● Challenges and conclusion
  • 4.
  • 6.
    Microservices ● Single responsibilityprinciple - “granularity” ● Faster developers onboarding ● Faster adding features ● Ease of deployment* ● Freedom to choose technology* ● High scalability
  • 8.
  • 9.
    ● Complexity ● Size(100s of files, 100s of KLOC) ● Size of the teams (10s developers) ● Technological diversity ● Constant upgrades and migrations
  • 11.
  • 12.
  • 13.
    Architectures FRONTEND BACKEND App1 App2 App3 Infra(BE4FE, NGNIX, etc) MS1 MS2 MS3 MS5 MS4 MS6 FRONTEND + BACKEND
  • 14.
  • 15.
    Solutions overview ● In-browser:single-spa ● Server-side: tailor ● iFrames & per-route apps ● Web components as wrapper
  • 16.
    In-browser: Single-spa github.com/CanopyTax/single-spa ● Inbrowser ● Lazy load ● Parts of one page & separate routes ● Share styles, utils, data, events etc. ● Unified lifecycle @legkoletat | Microservices in frontend: architectures and solutions
  • 17.
    Schema #1: Single-spa Widget app1 Widget app 2 Dashboard app Single-spa + config Header app index.html
  • 18.
    Single-spa: root config //single-spa-config.js import{declareChildApplication, start} from 'single-spa'; declareChildApplication('app-user-profile', () => import('PATH_TO/app.user.profile.js'),pathPrefix('/profile’)); declareChildApplication('app-transactions', () => import('PATH_TO/app.transactions.js'),pathPrefix('/transactions’)); //etc start();
  • 19.
    Single-spa: configure app //app-user-profile.js export function bootstrap(props) { return Promise .resolve() .then(() => { // one-time app initialization code }); } //mount callback //unmount callback
  • 20.
    Stitching fragments github.com/zalando/tailor ● Backendpowered (NodeJS) ● Serves parts of one page ● Provides complete toolset - Mosaic
  • 21.
    Widget app 1 Schema #2:Tailor github.com/shershen08/tailor-vue-demo Widget app 2 Dashboard app Tailor + Webserver Header app HTML-like template @legkoletat | Microservices in frontend: architectures and solutions
  • 22.
    Tailor server const Tailor= require('node-tailor'); const tailor = new Tailor({ templatesPath: '/built-apps-folder' }); const server = http.createServer((req, res) => { // custom server logic tailor.requestHandler(req, res) }) server.listen(process.env.PORT);
  • 23.
    Tailor template <body> <!-- header--> <div id="header"> <span class="fragment-error">Header failed to load</span> </div> <fragment src="https://abs123.company.internal.com"></fragment> <!-- dashboard --> <fragment src="https://dashb22.company.internal.com" primary> </fragment>
  • 24.
    Tailor app setup "scripts":{ "start": "npm run start-fragments & node tailor.js", "install-fragment-dependencies": "lerna bootstrap", "build-fragments": "lerna run build", "start-fragments": "lerna run --parallel start", "watch-fragments": "lerna run --parallel dev" }, App1 app1.min.js assets/ Serve to tailor Single repo per app: Or in monorepo: Pipeline
  • 25.
    Single app perroute ● Easy to setup ● No direct interaction ● Transfer state ● Control styles Image from Elisabeth Engel: Break Up With Your Frontend Monolith
  • 26.
    iFrames ● Security ● Contentadjustment - size, scroll ● Data exchange (via postMessage) ● Control styles //app 1 window.addEventListener("message", receiveMessage, false); //app 2 window.postMessage("hello there!", "http://example.com");
  • 27.
    Widget app 1 Schema #3:App per route & iframe Widget app 2 Dashboard app Header app Separate repos, pipelines, etc Header No SPA State: via server or request params
  • 28.
    Framework + Webcomponents ● WCs in 2019 are widespread and supported ● DOM & styles can be isolated ● From apps to single components
  • 29.
    Framework + Webcomponents github.com/vuejs/vue-web-component-wrapper Example for Vue, same can be for Angular, React, Svelte, etc
  • 30.
    Glimpse of future:Portals <portal id="myPortal" src="https://www.example.com/"></portal> github.com/WICG/ Secure and seamless navigation Portal can be activated myPortal.activate({ data: [...] }); Other document (portal) listens to activation, loads data and react window.addEventListener('portalactivate', e => { let predecessor = e.adoptPredecessor(document); //etc
  • 31.
  • 33.
    Technical challenges ● Morecomplex setup ● Managing state and passing data & events ● Predictable and reusable styles ● Page code size (TTI, loading, debugging) var bus = new EventBus(); bus.on('someEvent', function (data) { console.log('got ' + data); }); bus.on('someEvent', function foo () { bus.off('someEvent', foo); });
  • 34.
    Non-technical challenges ● Onboardingnew developers ● Team composition ● Knowledge transfer ● More moving parts (compatibility, upgrades)
  • 35.
    Pros Single Responsibility Principle Fastonboarding and adding features Ease of testing, deployment Freedom to choose technology @legkoletat | Microservices in frontend: architectures and solutions
  • 36.
    Do you reallyneed this? 1. Business profile 2. Application usage profile 3. Size of codebase 4. Infrastructure 5. Size, stablity and maturity of team
  • 37.