micro frontend · 2 4 1 5 microservices benefits small & specialized teams easier to scale...

Post on 16-Jul-2020

6 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Micro FrontEndThe microservices puzzle extended to frontend

Classic Study Case

An History of Evolution

Front-End

Back-End

Database

Monolith

Front-End

Front & BackFront &

Microservices

Back-End

Database Prod

uct

serv

ice

Sear

ch

Serv

ice

Chec

kout

se

rvic

e

Front-End

It’s Not Only About Architecture

Front-End

Back-End

Database

Monolith

Front-End

Front & BackFront &

Microservices

Back-End

Database Prod

uct

serv

ice

Sear

ch

Serv

ice

Chec

kout

se

rvic

e

Front-End

The Pet Store Team

The Front End Team

The Back End Team

The Front End Team

Prod

uct

Team

Sear

ch

Team

Chec

kout

Te

am

42

1 5

Microservices Benefits

Small & Specialized

Teams

Easier to scale

Micro Services

Freedom in stack’s

choicesEasier to deploy

3

4

Front & Microservices: The perfect match?

Front & Microservices

Prod

uct

serv

ice

Sear

ch

Serv

ice

Chec

kout

se

rvic

e

Front-EndThe Front End Team

Prod

uct

Team

Sear

ch

Team

Chec

kout

Te

am

Next Step of Evolution

Product Team Search Team Checkout Team

Front-End

Back-End

Database

Front-End

Back-End

Database

Front-End

Back-End

Database

Classic E-Commerce Approach

The Petstore Reloaded

Search Team

Product TeamCheckout Team

Customer Focused Teams

Product Team Search Team Checkout Team

Front-End

Back-End

Database

Front-End

Back-End

Database

Front-End

Back-End

Database

Customer Focused Teams

Product Team Search Team Checkout Team

Front-End

Back-End

Database

Front-End

Back-End

Database

Front-End

Back-End

Database

Mission:present the

product in a clear way

Mission:help finding the

right product quickly

Mission:make the checkout

experience easy

3

4

5

2

1

Micro Frontend Benefits

Freedom in stack’s

choicesSmall

Customer Centric Teams

Autonomous development Autonomous

release of features

Application’s evolution made easier

Micro Frontend

Real Life Study Case

July 2015

Manager

March 2017

Governance

August 2017

Operations

: Data Fabric

Real Life Study Case: Data Fabric

V2 is comingTime to reorganize the team!

OCT 2017

December 2017

Layout

March 2018

Galaxy

July 2018

Layout-as-lib

Data Fabric V2

Design System (aka saagie-ui)

Try #1: Saagie-Layout

Try #1: Saagie-Layout

What’s a Web Component?

Custom Elements

Shadow Dom HTML Template

ES Modules

<my-component>

My-component.js Index.htmlclass MyComponent extends HTMLElement {

connectedCallback() { // element has been attached to the DOM }

disconnectedCallback() { // element has been detached from the DOM }

attributeChangedCallback() { // an attribute value has changed }

render() { this.innerHTML = ̀ <div> … </div>`; }}

customElements.define('my-component', MyComponent);

<html lang="en"><head> <title>My application</title>

</head><body>

</body></html>

<script type="module" src="my-component.js">

</script>

<my-component></my-component>

<script src="/lib/document-register-element.js"> </script>

Talking about support...

source

Saagie-Layout

Saagie-Layout

From an Application To a Web Component

class DataManager extends HTMLElement {

constructor() { this.render(); }

render() { this.platform = this.getAttribute('platform'); this.innerHTML =

}}

angular .module('data-manager') .controller('AppController',

AppController);

AppController.$inject = ['$scope', '$rootScope', '$state', … ];

function AppController($scope, $rootScope, $state, ...) {

…}

app-controller.js data-manager.js

customElements.define('saagie-data-manager',DataManager);

`<div ng-app="data-manager" ng-controller="AppController"> <platform-nav platform=${this.platform}> </platform-nav> </div>`;

From an Application To a Web Component

class DataGovernance extends HTMLElement {

connectedCallback() { this.render(); }

render() { this.apiPath = this.getAttribute('datagov-url'); this.innerHTML =

}}

@Component({ selector: 'data-governance’, templateUrl: './app.component.html', providers: []})export class AppComponent {

… }

app-component.js data-governance.js

`<data-governance id="data-governance" datagov-url=${this.apiPath}> </data-governance>`;

customElements.define('saagie-data-governance', DataGovernance);

Saagie-Layout

index.html<html lang="en"> <head>

</head>

<body>

</body></html>

<link rel="stylesheet" href="/saagie-ui/src/index.css">

<script src="/data-governance/web-components/data-governance.js"> </script>

<script src="/data-fabric/web-components/data-manager.js"> </script>

<sla-board></sla-board>

Saagie-Layout

class Board extends HTMLElement {

render(path, user) { const page = this.getPage(path); this.innerHTML =

} …

getPage(path) { let page; switch (path) { case PROJECTS : page = `<saagie-data-manager

id="data-manager" platform=${getSelectedPlatform()}> </saagie-data-manager>`;

break;

case GOVERNANCE : page = `<saagie-data-governance

id="data-governance" datagov-url="${this.dataGovUrl}">

</saagie-data-governance>`;break;

} }}

board.js

`<div class="sui-l-app-layout"> <sla-topbar currentPage="${path}">

</sla-topbar>

<account-menu currentUser="${user}"> </account-menu>

<primary-nav></primary-nav>

<div class="sui-l-app-layout__page"> ${page}

</div> </div>`;

customElements.define('sla-board', Board);

Pros & Cons

ConsPros● consistent user experience ● not a true SPA

● high dependencies on libraries between apps

● bad performances

● routers management● implies to run the entire

stack locally

● possibility to display several components on the same page

● independent deployment

Try #2: Galaxy

Pros & Cons

ConsPros● possibility to share

components between applications

● still high dependencies on libraries between apps

● centralized routing system● but also between React’s

versions

Try #3: Layout-as-Lib

Layout-as-Lib

<html><head> <title>Saagie Governance</title></head><body id="sui-root">

<data-governance-angular class="sui-l-app-layout__subapp"> </data-governance-angular>

</body></html>

index.htmlimport {AppModule} from './app/app.module';

import {LoadLayoutData} from 'saagie-layout-lib';

platformBrowserDynamic().bootstrapModule(AppModule);

main.ts

<saagie-layout current-platform-object='{"loading": true}' hide="true">

</saagie-layout>

const legacy = window .location .pathname.startsWith('/datagovernance');

if (!legacy) { const hrefParameters = window.location.href.split('platform/');

new LoadLayoutData().init('governance', parseInt(hrefParameters[1], 10));

const layout = document.querySelector('saagie-layout'); layout.removeAttribute('hide');}

Layout-as-Lib

import '@webcomponents/custom-elements';

import './web-components/Layout';import './web-components/PrimaryNav';import './web-components/Topbar';

index.jsexport default class LoadLayoutData {

LoadLayoutData.js

import LoadLayoutData from './services/LoadLayoutData';

export default { LoadLayoutData}; async loadData(layoutComponent, currentApp,

currentPlatformId) {

await this.loadRights(); await this.loadJobsData(); await this.loadProfile(); }

init(currentApp, currentPlatformId) { const layoutComponent = document.querySelector('saagie-layout');

return this.loadData(layoutComponent, currentApp, currentPlatformId); }}

Layout-as-Lib

import '@webcomponents/custom-elements';

import './web-components/Layout';import './web-components/PrimaryNav';import './web-components/Topbar';

index.jsexport default class LoadLayoutData {

LoadLayoutData.js

import LoadLayoutData from './services/LoadLayoutData';

export default { LoadLayoutData};

async loadRights(){ const rights = await fetch(apiRightsUrl); this.login = rights.login; this.setUser({ login: this.login }); this.setPlatforms(rights.platforms)); }

setPlatforms(platforms) { this.layoutComponent .setAttribute('platforms-list-object', JSON.stringify({platforms})); }

Layout-as-Lib

layout.jsclass Layout extends HTMLElement { …

initRender() { this.innerHTML = `<div class="sui-l-app-layout" id="sui-root">

<saagie-topbar class="sui-o-topbar"> </saagie-topbar> <saagie-primary-nav class="sui-o-primary-nav"> </saagie-primary-nav> ${this.innerHTML}

</div>`; }}

connectedCallback() { this.initRender(); … }

attributeChangedCallback(name, oldValue, newValue) { switch (name) { case 'current-app': this.changeChildAttribute ('saagie-topbar', name, newValue); this.changeChildAttribute ('saagie-primary-nav', name, newValue); break;

case 'current-platform-object': …

if(!customElements.get('saagie-layout')){ customElements.define('saagie-layout', Layout);}

Pros & Cons

ConsPros● not an SPA at all● no components

aggregation possible

Page Transitions

Page Transitions

Page Transitions

Page Transitions

Pros & Cons

ConsPros● way more faster● easier to integrate

● breaking changes implies to update each application

● possible inconsistent user experience

● independent deployment AND development

● no more libraries conflict● can be run on its own

Data Fabric

July 2015

Manager

March 2017

Governance

August 2017

Operations

Data Fabric V2

V2 is comingTime to reorganize the team!

OCT 2017

December 2017

Layout

March 2018

Galaxy

May 2018

Security

Data Fabric V2

September 2018

Project & Jobs

July 2018

App StoreDecember 2018

Dataset Access

June 2018

Layout-as-lib

Best practices, tips & tricks

Think usecase first Take care of your design

Share ressources, not runtime!

Aggregation of components or aggregation of SPA?

Design system, optimistic UI, skeletons ...

Build independent and self contained apps

Share libraries and common services

● Micro-frontends.orghttps://github.com/neuland/micro-frontendsMicro Frontends talk by Michael Geers at Web Rebels, Oslo 2018 @nataltis

● Experiences Using Micro FrontEnds at IKEAhttps://www.infoq.com/news/2018/08/experiences-micro-frontends

● Project Mosaic (Zalando)https://www.mosaic9.org/

● Single SPAhttps://single-spa.js.org/

To go further

Thank you!

top related