SPA(Single Page Application)のパフォーマンス測定には,特有の課題がいくつも存在する。Philip Tellis,Nicholas Jansma両氏は,アムステルダムで開催されたVelocityカンファレンスでこの問題を深く追及し,このようなアプリケーションのパフォーマンス評価を行う上での問題点と,それに対する具体的なアドバイスを提供した。
パフォーマンス関連製品ベンダのSOASTAでチーフアーキテクトを務めるTellis氏は,人気の高いboomerangライブラリの作者でもあり,Jansma氏は同社のシニアソフトウェアエンジニアである。
両氏はハードナビゲーションとソフトナビゲーションという区別を用いる。ハードナビゲーションとは,初期ルートのレンダリングを含むSPAの最初のページロードであり,それに続くルート変更がソフトナビゲーションである。
何らかの測定を行うには,その開始と終了がいつなのかを知らなければならない。 ソフトナビゲーションが存在するため,SPAではこれが問題となる。onload
イベントはもはや意味をなさない。大部分のアクティビティはそのイベント以降に発生するからだ。実際にはナビゲートせずに,つまりonload
イベントを起動せずに,ブラウザのURLを変更することができるという意味から言えば,ソフトナビゲーションは本当の意味でのナビゲーションではない。さらにブラウザには,リソース - イメージやスクリプト,CSS,ビデオなど - をいつ,どのような理由でダウンロードしたかを通知するAPIは存在しない。自動的に実行されるソフトナビゲーションの開始イベントと終了イベントを知るためには,ヒューリスティックな手法が必要だ。
ソフトナビゲーションの発生を検出する方法はいくつかある。ブラウザの履歴が変更されるかも知れない。AngularJSの$routeChangeStart
イベントのように,SPAフレームワークが特定のルーティングイベントを起動する場合もある。ユーザがいずれかのDOM要素をクリックしている可能性もある。あるいは,XHR (XmlHttpRequest)がDOM変更を起動するかも知れない。ただし,これらのイベントはいずれも,それ自体でソフトナビゲーションを通知するものではなく,それに続くイベントでリソースのフェッチやDOMの大幅な変更,あるいはブラウザの履歴変更などがあるかどうかによる。
ソフトナビゲーションの終了イベントが何であるかは,コンテキストによって決まる。すべてのリソース取得の完了かも知れないし,ユーザとのインタラクションの完了,あるいは他のイベント完了の可能性もある。両氏が推奨するのはネットワークアクティビティを監視する方法だ。そのためにはXHR要求と,img
タグなどDOM要素による暗黙的なリソース読み込みの両方をインタセプトする必要がある。Bppmerangは,これらのシナリオを処理するプラグインとして,auto_xhrを提供している。このプラグインは,XHRオブジェクトをプロキシしてサーバ要求を監視すると同時に,Mutation Observerを利用してリソースの取得に関連するDOMの変更(src
やhref
属性の更新など)を監視する。
リソースのダウンロードだけではなく,ブラウザのレンダリング更新(イメージ描画など)に要する時間の測定も重要だ。setTimeout(..., 0)
を使うことで,パフォーマンス計測の前にレンダリングを行うことができる。
var xhr = new XMLHttpRequest();
xhr.open("GET", "fetchstuff");
xhr.addEventListener("load", function(){
$(document.body).html(xhr.responseText);
setTimeout(function() {
var endTime = Date.now();
var duration = endTime - startTime;
}, 0);
});
var startTime = Date.now();
xhr.send();
この複雑な状況は,将来的に変わるかも知れない。WHATWG (Web Hypertext Application Technology Working Group)が現在,リソースフェッチを統一化するために,一貫性のあるAPI提供を目的としたFetch標準に取り組んでいるからだ。
User Timing APIはそれ自体,特定のパフォーマンス測定のために標準化されたAPIである。ビジネストランザクション対応の計測を有意に行う上では,最善の方法を提供する。欠点は,測定値毎に特別なコードが必要なことだ。
ハードナビゲーションについては,そのタイミングに関連するAPIが既に用意されている。Navigation Timing APIを使えば,詳細な関連情報にアクセスすることが可能だ。Resource Timing APIを使って,リソース読み込みのタイミングに関する詳細な情報を取得できるが,ブラウザがリソースをロードしているかどうかを知る手段がない点には注意が必要である。これらのAPIは元々,SPAアプリケーションのコンテキストを対象としたものではない。
講演で使用された資料はSlideShareに公開されている。