Migrating from Monolith to Microfrontends

Yaprak Ayazoğlu

ConfrontJS 2018

@yaprakaya

About me...

Yaprak Ayazoğlu

Freelance Frontend Engineer

Google Developer Expert in Web Tecnologies

@yaprakaya

  • Netherlands in the past 4 years
  • M.S. Computer Science
  • B.S. in Electrical and Electronics Eng.
  • 1 Solar powered and Hydrogen Powered car
  • Mentoring @LoncaWorks

 

@yaprakaya

@yaprakaya

@yaprakaya

bol.com

@yaprakaya

What am I doing @bol.com?

@yaprakaya

Change...

Webshop ->Sellers

@yaprakaya

When I started @bol.com

@yaprakaya

Architecture

  • Monolith
  • Java in the backend
  • A mixture of Angular 1.x, Backbone, Handlebars in the frontend

@yaprakaya

Domains in Seller Dashboards

@yaprakaya

@yaprakaya

Monolith

Seller Dashboards

Returns

Orders

My Assortiment

...

Downstreams

Pain points

  • Deployment
  • Code reuse
  • Inertia (hard to adapt and implement new ideas)
  • Maintenance
  • Owneship

@yaprakaya

Time to change...

@yaprakaya

Expectations

  • Teams that can work independent of each other
  • Publishing code flawless and being able to publish frequently
  • Able to adapt and implement innovations
  • Using new technologies
  • Migrate without affecting the end users

@yaprakaya

Domains

  • /orders
  • /offers
  • /home
  • /performance
  • /assortment
  • /returns
  • ... vs.

@yaprakaya

Before...

@yaprakaya

Monolith

Seller Dashboards

Returns

Orders

My Assortiment

...

Downstreams

After Return Domain Detached

@yaprakaya

Monolith

Seller Dashboards

Returns

Orders

My Assortiment

...

Downstreams

FE

BE

@yaprakaya

BFF (Backend for frontend)

Backend for Frontend is a shim to help organize microservice architectures and coordinate functionality across a diverse, wide system. A BFF is a layer between the downstream services and UI.

Microfrontend

A composition of techniques, strategies and recipes for building a modern web app with multiple teams using different JavaScript frameworks.

@yaprakaya

Examples of Micro Frontend

  • Orders
  • Returns
  • Delivery services
  • Warehouse management

@yaprakaya

@yaprakaya

Monolith

Seller Dashboards

Returns

Orders

My Assortiment

...

Downstreams

FE

BE

FE

BE

...

Features

  • It does not own data
  • including session
  • Independent of each other
  • Reusable in different portals
  • Live in different urls, different servers, different machines

@yaprakaya

Single Sign On

  • Session information
  • First service that detached from seller dashboard
  • The service without UI
  • Key microservice that makes the system look like one complete system

@yaprakaya

Menu

@yaprakaya

As we speak...

  • 8 different teams who works in 6 different departments
  • More than 20 micro frontend
  • Services that are deployed for several different user groups and different portals

@yaprakaya

Problems

  • The same look and feel and user experience
  • Shared libraries
  • SSO
  • Problems in hardware level

@yaprakaya

Was it a success in first take?

@yaprakaya

The first microfrontend experiment

  • Supplier portal
  • Angular Module for each domain
  • A SPA that is glued to each other on the browser

@yaprakaya

Supplier Portal

Application

1

Application

2

Application

3

@yaprakaya

SPA structure

<html>
  <head>
    …
    <script src=“/wrapper/bundle.js”></script>
    <script src=“/application-1/bundle.js”></script>
    <script src=“/application-2/bundle.js”></script>
    <script src=“/application-3/bundle.js”></script>
    …
  </head>
  …
</html>

@yaprakaya

Downs

  • Hard to maintain
  • Separate repositories become dependent to each other on run time
  • 3rd party library updates affected whole system

@yaprakaya

Ups

  • Performance

First of all...

  • Supplier portal is still in use

Modern Technologies

@yaprakaya

@yaprakaya

Typescript

  • Able to define types
  • Able to define interface for REST communication
  • Able to define types for streams (Observables)
  • Editor support

@yaprakaya

@yaprakaya


@Injectable()
export class PackingListService {
  private packingListUrl = 'url/to/packing-list';

  constructor(public http: HttpClient) { }

  public getPackingList(listId: string): 
      Observable<SendStockItem[]> {
    return this.http
      .get(`${this.packingListUrl}?list-id=${listId}`)
      .map((json: any) => {
        const packingList = PackingListDto.fromJson(json);
        return packingList.lines;
      });
  }
}

@yaprakaya

import { SendStockItem } from './send-stock-item';

export class PackingListDto {
  id: string;
  retailerId: string;
  sendStockItems: SendStockItem[];

  static fromJson(json: any): PackingListDto {
    return PackingListDtoSerializer.fromJson(json);
  }
}

class PackingListDtoSerializer {
  static fromJson(json: any): PackingListDto {
    const packingListDto = new PackingListDto();
    packingListDto.id = json.id;
    packingListDto.retailerId = json.retailerId;
    packingListDto.sendStockItems = json.lines.map((line) => {
      return SendStockItem.fromJson(line);
    });
    return packingListDto;
  }
}

@yaprakaya

import { FormGroup } from '@angular/forms';

export class SendStockItem {
  id: string;
  selectedQuantityFormItem?: FormGroup;

  static fromJson(json: any): SendStockItem {
    return SendStockItemSerializer.fromJson(json);
  }
}

class SendStockItemSerializer {
  static fromJson(json: any): SendStockItem {
    const sendStockItem = new SendStockItem();
    sendStockItem.id = json.id;
    return sendStockItem;
  }
}

Angular

  • Component based
  • Form and validation support
  • Localization support
  • Dependency injection in unit tests
  • CLI
  • Ecosystem
  • Framework

@yaprakaya

Shared libraries

@yaprakaya

Styling

@yaprakaya

Angular Component

Library

 

@yaprakaya

Framework agnostic component library and style guide

@yaprakaya

Wrap up

  • Autonomous and independent teams
  • Ownership
  • Easy to adapt new ideas
  • New technologies

@yaprakaya

Questions?

@yaprakaya

Thanks

@yaprakaya

https://frontconnect.nl/

info@frontconnect.nl

https://slides.com/yaprakayazoglu/monolith-to-microfrontend/