bokken.io
作成日
2023-04-30
更新日
2023-04-30
author
@bokken_
tag
Browser, Timing API, Performance

Web サイトのパフォーマンスを計測するためのタイミング関係の API について

はじめに

Web サイトのパフォーマンスはビジネスにもインパクトを与える事があると言われている(参考)。 また、Google は検索ランクについて Core Web Vitals を考慮するということを発表している。このことから、パフォーマンスを改善することは非常に重要であるといえそうだ。

パフォーマンスを改善するためには、まず計測できるようになる必要がある。昨今では様々なユーザ環境のパフォーマンスを計測するツールが提供されている。 本記事ではこれらのツールが一体どういった方法でパフォーマンスを計測しているのか、特に Performance Timeline という仕様に絞って紹介する。

Performance Timeline API はどういう考え方でパフォーマンスの情報を提供しているか

Performance Timeline という仕様がベースになっている。 こちらの仕様には、Performance Observer が定義されている。この Performance Observer に、計測したいメトリクスを定義することで、そのメトリクスを Observe して知らせてくれる。

この Performance Observer を使えば、例えば次のような形でパフォーマンスメトリクスを監視し、メトリクスの保存場所へ送ることになるだろう。

const observer = new PerofmranceObserver((entryList) => {
    for(const entry of entryList.getEntries()) {
        console.log(entry);
    }
}).observe({ type: "layout-shift"});

PerformanceObserver は、それまでに起こったエントリも buffer もされているため、すでに過ぎたイベントも粗めてエントリとして取得できる。また entryTypes を指定することで複数のエントリも指定できる。

// buffer されたエントリも取得する
const observer = new PerofmranceObserver((entryList) => {
    for(const entry of entryList.getEntries()) {
        console.log(entry);
    }
}).observe({ type: "layout-shift", buffered: true});

// entryTypes という形で複数のエントリタイプを指定する
const observer = new PerofmranceObserver((entryList) => {
    for(const entry of entryList.getEntries()) {
        console.log(entry);
    }
}).observe({ entryTypes: ["first-input", "layout-shift]})

現在策定されている指標

Performance Observer で監視できるものは Performance Entry と呼ばれており、 Timing Entry Names Registry によると、現状 Performance Entry には次の 11 種類の type が存在している。 それぞれ 2023 年 4 月 25 日現在の主要 3 ブラウザ が API の対応状況は次の表のようになっている。

entryType Interface Type Chrome Firefox Safari
mark PerformanceMark o o o
measure PerformanceMeasure o o o
navigation PerformanceNavigationTiming o o o
resource PerformanceResourceTiming o o o
longtask PerformanceLongTaskTiming o x x
paint PerformancePaintTiming o o o
element PerformanceElementTiming o x x
event PerformanceEventTiming o o x
first-input PerformanceEventTiming o o x
layout-shift LayoutShift o x x
largest-contentful-paint LargestContentfulPaint o x x

これらのエントリを使えば Core Web Vitals も計測できるようになる。例えば、 Largest Contentful Paint は次の様な形で取得できる。

const observer = new PerformanceObserver((entryList) => {
    const entries = entryList.getEntries();
    const lastEntry = entries[entries.length - 1];
    if (lastEntry) {
        const lcp = lastEntry.startTime - performance.getEntriesByType('navigation')[0].activationStart;
        console.log(lcp);
    }
}).observe({ type: "largest-contentful-paint", buffered: true});

厳密には、Prerender2 の際や、BFCache によって復元された場合には navigation のスタートタイミング (0) からではなく、window が activate されたタイミングや、BFCache が restore されたタイミング (0 ではなくなる) ため、少し工夫が必要になる。より厳密に計測したい場合は web-vitals を参考にすると良いだろう。

デモ

Performance Entry を確認するためにデモサイトを用意した。上記の Performance Entry をすべて確認できるようになっている (一部操作が必要)。

次のように少し操作することで Performance Entry が取得できているのが分かる。

新しく追加されているエントリの種別

ここまで Timing Entry Names Registry で紹介されている Performance Entry を紹介したが、Timing Entry Names Registry は 2021 年 2 月から更新がされていない。 現状、新しくエントリが増えていないのか、Chrome の DevTools の console で PerformanceObserver.supportedEntryTypes を実行したところ、あたらしく 3 つのエントリ (back-forward-cache-restorationsoft-navigationvisibility-state) が追加されていることを確認できた。

PerformanceObserver.supportedEntryTypes
> (14) ['back-forward-cache-restoration', 'element', 'event', 'first-input', 'largest-contentful-paint', 'layout-shift', 'longtask', 'mark', 'measure', 'navigation', 'paint', 'resource', 'soft-navigation', 'visibility-state']

これらは Chromium ベースのブラウザでのみ利用できるようだが、これらについても簡単に表にまとめておく。

エントリ 説明 関連 link
back-forward-cache-restoration BFCache で restoration されたタイミング * https://bugs.chromium.org/p/chromium/issues/detail?id=1273925
soft-navigation SPA などで別ページに移動することなく画面遷移した際のタイミング * https://groups.google.com/a/chromium.org/g/blink-dev/c/IK-IZTBo59U/m/r8WaR2YOBQAJ
visibility-state ウィンドウが見える状態と隠れた状態が切り替わったタイミング * https://groups.google.com/a/chromium.org/g/blink-dev/c/LA8HTx6tCKY/m/6VkL0jxtAQAJ

その他

これまで紹介した API は比較的簡単に Performance 情報を取得できる。 その他にも Chromium ベースのブラウザの場合は ${browse識別子}://tracing/ にアクセスすることで、より詳細なパフォーマンスの情報を取得できる。こちらはよりブラウザの詳細な実行状況を取得できるため情報量は多い。ただ、これはパフォーマンスに問題意識を感じた開発者やユーザが自ら実行するもので、RUM サービス提供者が使えるようなものではない。これまで紹介してきた API は開発者やユーザはもちろん、 RUM サービス提供者も利用できるようになっている。

おわりに

ここまでパフォーマンスの計測ができる各種 API についてまとめて、対応状況等と合わせて紹介した。 Performance Observer によって一箇所に Performance 系のエントリがまとめて入ってくる API は拡張しやすそうに感じた (実際に続々と追加されていそうだ)。

一方で、これらの Performance Entry の扱いには少しクセがあり、BFCache によって restore されたのか、Prerender2 による navigation かなどによって、各エントリの情報を加工して使う必要がある。そのためにはブラウザについて深い理解が必要だろう。RUM (Real User Monitoring) を提供しているサービスのすごさが少し理解できたように感じる。

今後も Web Vitals は増えていき、その分だけ Performance Entry は増えていくが、基本を理解していればそれほど戸惑わなくても済みそうだ。この記事がその一助になれば嬉しい。

もしも、誤りや補足の情報があれば issue@bokken_ までいただけると嬉しい。

参考資料・リンク

  1. Web Performance Working Group
  2. PerformanceEntry.entryType - Web APIs | MDN
  3. User Timing API
  4. Navigation Timing API
  5. Event Timing API
  6. Resource Timing API
  7. Frame Timing API

    This work is NO LONGER BEING PURSUED. It's left here for historical purposes.

  8. Performance Timeline
  9. Long Task API
  10. Server Timing
  11. Timing Entry Names Registry
  12. Performance observer - Efficient access to performance data - Chrome Developers
  13. Custom metrics
  14. Largest Contentful Paint (LCP)
  15. Google Developers Japan: Core Web Vitals によるビジネス インパクト
Tweet このエントリーをはてなブックマークに追加
Subscribe via RSS
TOP