FRONTEND

microservices

Maurizio Lupo (@sithmel)

Requirements:

  • optimising rendering perf.
  • being efficient in loading common components
  • keeping each application independent

Part 1: Javascript

Simplest case:

<div>service 1 markup</div>
<script async src="service1.js"></script>

<div>service 2 markup</div>
<script async src="service2.js"></script>
  • in the same page the same code is potentially loaded more than once
  • you can't cache the same libraries when navigating across the site

It is inefficient:

Common resources

<script src="common.js"></script>

<div>service 1 markup</div>
<script async src="service1.js"></script>

<div>service 2 markup</div>
<script async src="service2.js"></script>
  • optimising rendering performance (we have now a synchronous bundle)
  • keeping every application independent one another (what microservice should contain common.js?)

It is not compatible with 2 requirements:

Using async-define

<script async src="common_ad.js"></script>
<div>service 1 markup</div>
<script async src="service1_ad.js"></script>

<script async src="common_ad.js"></script>
<div>service 2 markup</div>
<script async src="service2_ad.js"></script>
  • optimising rendering performance (everything is async)
  • being efficient in loading common components (common components are factored out)
  • keeping every application independent one another (common_ad is downloaded only once because of the browser caching* and executed only once because of async-define).

This restores the 2 requirements:

Loading the same resource multiple times

Most browsers load only once (Chrome IE10, Safari)

If only we had something to remove duplicated resources ...

hint: Compoxure does that

async-define

It is an AMD runner: it manage the execution order of AMD bundles

It can be added in the bundling step, no messing with the source code (plugins for browserify, webpack and rollup).

It adds 0.5 KB to a bundle

Bonus: RESOURCE PRIORITY 

<link rel="preload" as="script" href="service1_ad.js" />
<link rel="preload" as="script" href="service2_ad.js" />

<script async src="common_ad.js"></script>
<div>service 1 markup</div>
... long markup with many images
<script async src="service1_ad.js"></script>

<script async src="common_ad.js"></script>
<div>service 2 markup</div>
... long markup with many images
<script async src="service2_ad.js"></script>

PART 2: CSS

SIMPLEST CASE

<link rel="stylesheet" href="service1.css" />
<div>service 1 markup</div>

<link rel="stylesheet" href="service2.css" />
<div>service 2 markup</div>
  • in the same page the same code is potentially loaded more than once
  • you can't cache the same libraries when navigating across the site

It is inefficient:

SINGLE BUNDLE

<link rel="stylesheet" href="main.css" />

<div>service 1 markup</div>

<div>service 2 markup</div>

It is not compatible with 2 requirements:

  • optimising rendering performance (we wait for the second bundle CSS to render the first service)
  • keeping every application independent one another

MICRO BUNDLES

<link rel="stylesheet" href="base.css" />
<link rel="stylesheet" href="forms.css" />
<link rel="stylesheet" href="service1.css" />
<div>service 1 markup</div>

<link rel="stylesheet" href="base.css" />
<link rel="stylesheet" href="forms.css" />
<link rel="stylesheet" href="buttons.css" />
<link rel="stylesheet" href="icons.css" />
<link rel="stylesheet" href="service2.css" />
<div>service 2 markup</div>

It looks very verbose but, compoxure spits out this:

<link rel="stylesheet" href="base.css" />
<link rel="stylesheet" href="forms.css" />
<link rel="stylesheet" href="service1.css" />
<div>service 1 markup</div>

<link rel="stylesheet" href="buttons.css" />
<link rel="stylesheet" href="icons.css" />
<link rel="stylesheet" href="service2.css" />
<div>service 2 markup</div>

MICRO BUNDLES

How browsers deal with CSS:*

It only blocks the rendering of the HTML under the CSS

*Chrome is currently being fixed

https://twitter.com/jaffathecake/status/829999531429392385

Bonus 1: RESOURCE PRIORITY

<link rel="preload" as="style" href="icons.css" />

<link rel="stylesheet" href="base.css" />
<link rel="stylesheet" href="forms.css" />
<link rel="stylesheet" href="service1.css" />
<div>service 1 markup</div>

<link rel="stylesheet" href="buttons.css" />
<link rel="stylesheet" href="icons.css" />
<link rel="stylesheet" href="service2.css" />
<div>service 2 markup</div>

Bonus 2: CSS ASYNC*

<link rel="preload" href="icons.css" as="style" onload="this.rel='stylesheet'">

<link rel="stylesheet" href="base.css" />
<link rel="stylesheet" href="forms.css" />
<link rel="stylesheet" href="service1.css" />
<div>service 1 markup</div>

<link rel="stylesheet" href="buttons.css" />
<link rel="stylesheet" href="service2.css" />
<div>service 2 markup</div>

*Requires a polyfill

Bonus 3: SERVER PUSH*

Link: </styles.css>; rel=preload; as=style

*Using HTTP2 CDN

In http header

<link rel="stylesheet" href="/style.css" />

Thanks

Maurizio Lupo (@sithmel)

Frontend microservices

By Maurizio Lupo

Frontend microservices

  • 527