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.
- Device: Nexus 5 device emulation
- Network: 1.6 Mbps network throttling
- url: http://localhost:4000/v2/guide
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
It will be nice to show fallback font as soon as possible and add progressive enhancement strategy to the site.
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
So, adding defer attribute to all these scripts (except vue.js, we will manage it later) brought us to this results:
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
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.
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.
FMP, FCP under `2 sec`
TTCI, TTCI, PSI under `5 sec`
Statistic results are good but user experience is not nice.
There are several libraries which can help monitor loading fonts:
I tried fontafaceobserver by Bram Stein.
So, results are:
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.
Supported in Chrome and about to be supported in Firefox
For this case `font-display: swap` was used
| | 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.
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.