Micro Frontends

Think Smaller, Avoid the Monolith
Love the Backend

Web Rebels, Oslo 2018 | Michael Geers

20052018technology evolves quickly?

frontend gets bigger

Michael Geers
Frontend Engineernaltatis
on Twitter & GitHub

e-commerce

Bremen, Germany

Micro Frontends
Small Frontends?
Microservices in the Frontend? !

Micro Frontends
Verticalized Teams
Self Contained Systems
Vertical Decomposition
UI CompositionWahsit?
ithW

siy?
retteb
ito
Hotw

pim?
tnemleBackend

The ProjectFrontend

Frontend
BackendFrontend

BackendFrontendAPI Gateway (Rest, BFF, GraphQL, …)Backend

TeamInspire

ProductService

TeaserServiceTeam
SearchPriceServiceTeam
DecideAvailability
ServicePayment
ServiceTeam
Checkout

BasketService

Customer
Service

Microservice Architecture

FrontendFrontend
Backend

TeamSearch

Team
DecideTeam
Checkout

Micro Frontends

TeamInspireFrontend

Cross
Functional
Team

Backend

Team
Inspirestores its

Own Data

ships its

Own UITeam
SearchTeam
DecideTeam
is assigned a
Checkout

Specific Mission
has its own

Technology Stacksmells like a Fat & Tall Microservice

Self Contained Systems

is run by a4 projects

How we use thise-commerce

4-8 people
per team

2-7 teams
per projectOthers who work like thisOtto
Hello Fresh
SpotifyIkea

FacebookZalandoAmazon?
AutoScout24

gutefrageO!ce 365

Why Micro Frontends?

Development Speed

Small Autonomous Teams
with a clear mission

Customer Focus
every team ships directly
no pure api teams

Reduced Scope

Reduced Scope

everything fits
into memory again ❤
myFrontend Renovation

without throwing everything away

How to implement?

A Page is Owned by one Team
connected via Links<html>…

Homepage…
</html>ProductList

Team Inspire

ProductDetails

Team DecideBasket

Success

Team Checkout

Team Decideowns the page

Team Inspire

provides a fragment

Team Checkout
provides two fragments

Integration in the Browser

HTMLImports

HTMLTemplate

Web Components
CustomElements

Shadow
DOM

Custom Elements<checkout-basket></checkout-basket>

https://developers.google.com/web/fundamentals/getting-started/primers/customelements

Custom Elements
class CheckoutBasket extends HTMLElement {connectedCallback() {this.innerHTML = 'mini basket ...';}}

customElements.define('checkout-basket', CheckoutBasket);Element Lifecycle
class CheckoutBasket extends HTMLElement {constructor() {...}

is createdconnectedCallback() {...}

attached to DOM

attributeChangedCallback(attr, oldVal, newVal) {...}
disconnectedCallback() {...}}

removed from DOM, cleanup!

someone change an attributeCustom Elements by Default

AngularElements

hyperHTML
Element

Browser Support
noitaryletdi
hsgi
nocin nredun

Custom Elements v1
API stabilized end of 2016

Browser Support
11withPolyfill (5KB)

https://github.com/WebReflection/document-register-element

<checkout-basket></checkout-basket><inspire-reco sku="t_red"></inspire-reco><checkout-buy sku="t_red"></checkout-buy>

<checkout-basket></checkout-basket>

neer
g
t_
<inspire-reco sku="t_red"></inspire-reco>

nee
r
g_t
<checkout-buy sku="t_red"></checkout-buy>theDOM is the API

Teams publish their Custom Elements documentation
Element-Name, Attributes, EventsFramework Support
Interoperability Test Suite
for Frameworks

custom-elements-everywhere.com
Rob Dodson@robdodson

But Progressive Enhancement?

But Progressive Enhancement?

Jeremy Keith@adactio

Resilient Web DesignIntegration on the Server

SSI Server Side Includes<!--#include virtual="/some-url" -->2001

Google Books

The easiest way to import external content
into a Web page is to use a server-side
include.
2001

Google Books

nginxServerTeam DecideServerTeam Checkout

Server Side Includes/red-tractor

/red-tractor

nginx

ServerTeam DecideServerTeam Checkout

Server Side Includes/red-tractor

/red-tractor

nginx<html><!--#include virtual=“/checkout/basket“ --><h1>Tractor</h1><!--#include virtual=“/checkout/buy“ --></html>ServerTeam DecideServerTeam Checkout

Server Side Includes/red-tractor

ServerTeam Decide/checkout/buy<html><!--#include virtual=“/checkout/basket“ --><h1>Tractor</h1><!--#include virtual=“/checkout/buy“ --></html>/checkout/basket/red-tractor

nginx

ServerTeam Checkout

Server Side Includes/red-tractor

ServerTeam Decide<button>buy for 66 €</button>/checkout/buy<em>0 items</em><html><!--#include virtual=“/checkout/basket“ --><h1>Tractor</h1><!--#include virtual=“/checkout/buy“ --></html>/checkout/basket/red-tractor

nginx

ServerTeam Checkout

Server Side Includes/red-tractor<html><em>0 items</em><h1>Tractor</h1><button>buy for 66 €</button></html>No Universal Web Components

Server Initial Render/inspire-reco?sku=t_red
res.send("<h3>Related Products</h3><ul>…")Browser Rehydration & User Interaction<inspire-reco sku="t_red"></inspire-reco>
el.innerHTML = "<h3>Related Products</h3><ul>…")Custom Elements ❤ SSI
clientserver<inspire-reco sku="t_red"><!--#include virtual="/inspire-reco?sku=t_red" --></inspire-reco><checkout-basket><!--#include virtual="/checkout-basket" --></checkout-basket><inspire-reco sku="t_red"><!--#include virtual="/inspire-reco?sku=t_red" --></inspire-reco><checkout-buy sku="t_red"><!--#include virtual="/checkout-buy?sku=t_red" --></checkout-buy>Page Transitions

Only Inside a TeamOne Router per Team

Team ATeam BSoft
Navigation/list

ClientRendered

Hard
Navigation/product

Page
RefreshSoft
Navigation/cart

ClientRendered/success

Top Level Router

Shared Universal Router & Page Fragments

HTML Shell
with Router<a-listname="toy"></a-list><a-productid="12"></a-product>

also take a look at single-spa<b-cart></b-cart><b-success></b-success>const routes = {'/:name': 'a-list','/p/:id': 'a-product','/cart': 'b-cart','/success': 'b-success'}

Page-Fragments

Shared Fundamentals
JS Polyfills

Tracking?
Error Reporting?

Basic Typography
CSS Resets

RUM?
App Shell?

Common Design System

As Global Stylesheet
à la Bootstrap

one globally included css fileincludes only stylingused via css classes
Pros- simple solution / easy to use- consistent lookCons- global css tends to grow- no easy way to detect unused css- breaking changes are hard

cdn.example.org/global/styleguide.css

As Versioned Package
distributed via npm
components with template & stylingPros- only used css is shipped- teams can upgrade independently- fragments don’t relay on outer styles
Cons- requires build process (webpack, …)- common html-templating needed- temporary visual inconsistencies

v1.3

v1.1

v1.3

v2-beta#perfmattersBe reasonable!
don’t use all frameworks togeher!
do you really need a big framework?

Measure Performance
set a performance budget & know your numbers

Some more things …

Don’t Share Stateno shared globals

Value Independence
its tempting to unify everything

Learn from Colleagues
teach them how CSS works

Talk to your Neighbors
share best practices

Ownership is important
use team prefixes when needed2anks for Listening
micro-frontends.org@naltatis

Credits

Colorful Wood Structure Alexas_Fotos
https://pixabay.com/en/background-colorful-woodstructure-3412048/

Clocks Pixabay

The Tool Guy Tirachard Kumtanom
https://unsplash.com/photos/UuW4psOb388

Woodshop Igor Ovsyannykov
https://unsplash.com/photos/iXV0i4Wo4yc

https://www.pexels.com/photo/london-new-york-tokyo-andmoscow-clocks-48770/

Octan Tower The Lego Movie

Unicorn d97jro
https://pixabay.com/de/lego-einhorn-spielzeug-671593/

https://www.youtube.com/watch?v=GZT5z4K6uw4
recaptioned by @peeofive

Browser Logos Cătălin Mariș

Action Bicycling Roman Pohorecki

Broken Escalator Skitterphotohttps://www.pexels.com/photo/action-bicycling-bikebiking-287398/

https://pixabay.com/photo-1746279
https://freesound.org/people/dobroide/sounds/15227/
https://freesound.org/people/sittstav/sounds/171665/

https://github.com/alrra/browser-logos

Four Playing Pieces Pixabay
https://www.pexels.com/photo/set-of-4-wooden-elongatedaccessory-209651/

Sad Lego Benny Cheezburger

Wooden Counter David Siglin

Wired Elements

https://www.pexels.com/photo/blur-blurry-bokeh-closeup-347139/

http://gph.is/1BCRCKh

https://wiredjs.com/

Tractors Manufactum

https://www.manufactum.com/tin-toys-c193667/

sdnetnorForbuilt with Mic