パフォーマンスチューニングを勉強したのでまとめた (Lighthouse編)

thumbnail

はじめに

Cyber AgentのWeb Speed Hackathon Vol.2に参加するのでフロントのパフォーマンスチューニングを少し勉強しました。(執筆時は未参加)

今回はLight House v6の指標についてまとめました。
web.devの内容をなぞっていきます。

パフォーマンス測定の指標

LightHouse 6は以下の6つの指標に基づいて測定される。()の数値は重視される比率。

  • First Contentful Paint (15%)

  • Speed Index (15%)

  • Largest Contentful Paint (25%)

  • Time to Interactive (15%)

  • Total Blocking Time (25%)

  • Cumulative Layout Shift (5%)



1. First Contentful Paint (FCP)

weight: 15%

FCP measures how long it takes the browser to render the first piece of DOM content after a user navigates to your page.

ユーザーがページに訪れた際に最初のDOMがレンダリングされるまでにかかる時間。

考えられる原因

  • Webフォントが読み込まれるまでテキストがレンダリングされていない

Ensure text remains visible during webfont load

→ 対応:

  1. font-display: swapを追加
  2. Webフォントをpreloadする
 <link rel="preload" href="/assets/Pacifico-Bold.woff2" as="font" type="font/woff2" crossorigin>

2. Speed Index

weight:15%

Speed Index measures how quickly content is visually displayed during page load.

どれだけ速く、ページが視覚的に表示されるか。

改善策

レンダリングプロセスの根幹を司るmain threadを最適化すべし。
main threadはHTMLのparse, DOMの構築, CSSのparseと適用, そしてJSのparse, 評価, 実行と言った、コードの大部分を扱う。
またmain threadはユーザーからの操作(イベント)に対応する為、常に忙しいが、これを後回しにするとUXへ影響する。 対応: (多すぎて書ききれない...)

  1. web workerを使用して、JavaScriptをmain threadで使用しない。(link: Use web workers to run JavaScript off the browser's main thread)
  2. CSSで複雑なセレクタや数値計算を避ける。

ダメな例
.box:nth-last-child(-n+1) .title { /* styles */ }
  1. CSSのminify, 使っていないコードの削除
  2. etc...

 MinificationとData Compressionをしよう。

Minification
CSS,JSなどのコードファイルのminifyをしろ。(webpack v4以降なら自動でやってくれるからいらないよ👍)

Data Compression
サーバー - クライアントのデータのやりとりを最適化しよう。GzipもしくはBrotliで。BrotliはGzipよりいいよ。
ブラウザへ送るファイルを圧縮するには DynamicStatic の2通りのやり方があるよ。どちらも一長一短だよ。

Dynamic comporession
リクエストが来た時にファイルを最適化するよ。手動で最適化したり、ビルド中にするより簡単だよ。けど圧縮率(?)が上がると遅延が生じるよ。
expressではcompression middlewareライブラリを使えば静的ファイルをgzipでdynamic compressionできるよ。

const express = require('express');
const compression = require('compression');

const app = express();

app.use(compression());

app.use(express.static('public'));

const listener = app.listen(process.env.PORT, function() {
    console.log('Your app is listening on port ' + listener.address().port);
});

Brotliにはshrink-rayが使えるよ〜

Static comporession
事前に最適化して保存しておくよ。ビルドが長くなるけどアクセス時の遅延は起こらなくなるよ。
webpackのpluginが使えるよ。


webpack.config.js
module.exports = {
    plugins: [
        new CompressionPlugin()
    ]
}

3. Largest Contentful Paint (LCP)

weight: 25%

The Largest Contentful Paint (LCP) metric reports the render time of the largest image or text block visible within the viewport.

viewport内で一番重い画像やテキストのレンダリング時間。

  • <img>
  • <svg>内での<image>
  • <video>
  • cssのbackground imageなど、url()を使うもの

対応

4. Time to Interactive (TTI)

weight: 15%

Measuring TTI is important because some sites optimize content visibility at the expense of interactivity. This can create a frustrating user experience: the site appears to be ready, but when the user tries to interact with it, nothing happens.

一定数のサイトはinteractivityを軽視してコンテンツの表示速度ばかり重視している。

指標

A page is considered fully interactive when:

  • The page displays useful content, which is measured by the First Contentful Paint,
  • Event handlers are registered for most visible page elements, and
  • The page responds to user interactions within 50 milliseconds.

FCPによって測定された有意なコンテンツが表示され、イベントハンドラがほとんどの要素に登録され、ユーザーの動作に50ms以内でに反応する事。

対応

5. Total Blocking Time (TBT)

weight: 25%

TBT measures the total amount of time that a page is blocked from responding to user input, such as mouse clicks, screen taps, or keyboard presses.

ユーザーの入力への返答がブロックされた時間(blocking portion)の合計。
50ms以上かかる処理はlong taskとされる。
例えば70msの処理は70 - 50で超過分の20msがblock portionとされる。
参考: Are long JavaScript tasks delaying your Time to Interactive?

対策:

  • Devtoolから時間がかかってるtaskがわかるよ~

What is causing my Long Tasks?

6. Cumulative Layout Shift (CLS)

weight: 5%

cumulative(意:累計)

レイアウトが頻繁に変わりすぎるページだとUXを損なうからよくないよ〜

対策

  • width,heightの動的な変更ではなく、 transform: scale()を使おう
  • top, right, bottom, leftを動的に変更せず、transform: translate()を使おう

気付き

  • 指標は6つあるが、改善策はそれぞれに固有の物ばかりでなく共通の物が多い。
    Minimize main thread work(JS)
    Reduce JavaScript execution time

  • ブラウザ(LightHouse)でJSファイルを見てもchunkされた状態になっているので、webpackのビルドプロセスを把握する必要がありそう。

 参考: https://qiita.com/mizchi/items/418be9abee5f785696f0

次回はwebpackの最適化とかをまとめていくつもりです。

目次

記事を読むのにかかる時間

50min