Artem Denysov

@denar90

Vue.js docs performance audit

Introduction

As far as mobile devices became more usable then desktops web faced the problem with slow applications. A lot of us test applications in Chrome and then ship. Not many developers try to test their applications on real devices and real networks.

So, I tried to follow these rules (partly) and test Open Sourced documentation for Vue.js framework — https://vuejs.org/

Test setup

Tools:

Problem:

pwmetrics results for vue.js docs

FCP — 3,5 sec

FMP — 4,6 sec

PSI — 6,1 sec

TTFP — 6,1 sec

TTC— 6,1 sec

Read more about these metrics in Performance metrics. What’s this all about?article.

There also some inconsistent behavior of FOIC (flash of invisible content) and FOUC (flash of unstyled content).

Different browsers behave differently
FOIC — Chrome, Firefox, Safari
FOUC — Edge, IE

FOIC

FOUC

It will be nice to show fallback font as soon as possible and add progressive enhancement strategy to the site.

Deferring scripts

But, first of all, scripts which are blocking First Paint should be managed.

Old but gold article about defer and async scripts behavior
FYI: ECMAScript6 modules are deferred by default

Timeline trace

So, adding defer attribute to all these scripts (except vue.js, we will manage it later) brought us to this results:

pwmetrics results after deferring scripts for vue.js docs

100ms for TTCI and TTFI metrics not so impressive but it’s something.

Adding defer to vue.js can save much more time:

FCP — 3,5 sec -> 1,9 sec

FMP — 4,6 sec -> 3,4 sec

PSI — 6,1 sec -> 4,9 sec

TTFI — 6,1 sec -> 4,9 sec

TTCI — 6,1 sec -> 4,9 sec

pwmetrics results after deferring vue.js
Adding defer requires to warp example codes into DOMContentLoaded listener, but I think it can be easily done in scope of `hexo-renderer-marked` fork.

Managing fonts

Timeline trace

Taking a look at timeline trace it can be noticed that fonts are blocking FMP just like scripts do.

Hence, some techniques can be applied to handle it.

Moving fonts into the body

Since browsers repaint after loading resources founded in body

fonts can be moved there.

Jake Archibald has really cool article about this behavior — The future of loading CSS.

Results

pwmetrics results for fonts resources in body for vue.js docs

FMP, FCP under `2 sec`

TTCI, TTCI, PSI under `5 sec`

FOIC demo

FOUC

Statistic results are good but user experience is not nice.

Thirdparty library

There are several libraries which can help monitor loading fonts:

I tried fontafaceobserver by Bram Stein.

So, results are:

Timeline trace

pwmetrcis results using fontafaceobserver for vue.js docs

FMP, FCP under `2 sec`, still the same

TTCI, TTFI, PSI under `5,2 sec` instead of `4,8 sec`

In case supporting all browsers, ~400ms looks like good trade off.

But.

font-display

Supported in Chrome and about to be supported in Firefox
For this case `font-display: swap` was used
pwmetrics results using font-display: swap for vue.js docs

FOIC demo

Comparing results:

|      |     before     | fonfaceobserver |    font-display    |
|:----:|:--------------:|:---------------:|:------------------:|
| FCP | 3,5 | 2 | 2,2 |
| FMP | 4,6 | 2 | 2,2 |
| PSI | 6,1 | 4,5 | 4,9 |
| TTFI | 6,1 | 5,3 | 4,8 |
| TTCI | 6,1 | 5,3 | 4,8 |

There are also some trade-off for FCP, FMP (200ms) but better for interactive time.

Either developing the new project or fixing an issue it is always a trade-off. We can’t have perfect scenarios all the time. Sometimes we should sacrifice.

So how to manage this situation? Which choice will be better?

I submitted PR to Vue.js org using fontfaceobserver because I thought they wanna support all browser, so case with font-display won’t work.

Results:

If you are working with evergreen browsers than don’t hesitate — use native supported features, use font-display .

Thank you for the reading.

P.S. I’ve written this article to show how in several steps you can improve speed for your application on mobile devices and slow networks really easy.

More by Artem Denysov

Topics of interest

More Related Stories