Facebook のフロントエンドは結構かわったことをやっていて、例えば、ログイン後の http://www.facebook.com/home.php には
<div id="pagelet_home_stream"></div>
みたいな空の HTML があり、その後に
<script>big_pipe.onPageletArrive({ … });</script> <script>big_pipe.onPageletArrive({ … });</script> ...
と script 要素が何個もならんでいる。
BigPipe: Pipelining web pages for high performance
この仕組みは (変数名のとおり) BigPipe と呼ばれていて、彼ら自身が BigPipe: Pipelining web pages for high performance で解説している。
かいつまんで説明しよう。通常、Web ページというのは
- ブラウザが http://example.com/foobar を要求する
- example.com のサーバーが /foobar にあるページを作るべく、MySQL などに問い合わせて、最終的には HTML にして送る
- ブラウザが送られてきた HTML をレンダリングする
といった感じでユーザーに届く。さてここで、サーバーが MySQL などに問い合わせている間、ブラウザは何をしているんだろうか。なにもしていない。ここではサーバーがボトルネックになっている。一方で、レンダリングがはじまると今度はブラウザがボトルネックになる。
サーバーの忙しさとブラウザの暇さ、あるいはその逆を (CPU の命令パイプラインのように) オーバーラップさせて全体の効率をあげる、というのが BigPipe の核となるアイデアだ。
実際の実装は
- サーバーは HTML の外枠を送信したら、一回ソケットを flush して
- ブラウザはそれをレンダリングして、BigPipe の JavaScript を読み込む
- サーバーは「友達リスト」や「更新情報」といった個々の部品 (BigPipe ではこれを "pagelet" と呼ぶ) をひとつづつ
- HTML まで作り、完成するごとに script 要素につめてブラウザに送信して、また flush し
- ブラウザは受信するごとに script 要素を実行し、既存の外枠の innerHTML に HTML をさしこんだり、CSS や画像、JavaScript のダウンロードをはじめる
- こうして、サーバーが最初の HTML をすべて送信し終わったときには、ブラウザ側のレンダリングもそれなりに終わっている
といった感じに動作する。iframe と multipart が合体したような感じ、という説明はわかりやすいんだかどうだか。
TTI: Time-to-Interact
Facebook が目指している「速さ」と、いままで Web ページで測っていた「速さ」には、ちょっと差がある。いままでは「ページの読み込み開始からレンダリング完了までに経過する時間」をいかに短くするかが勝負だったと思う。しかし、Facebook は「ページの読み込み開始から、ページ上でもっとも重要な部分が表示され、利用可能になるまで」というレンダリング途中の感覚値としての速さについても、考慮にいれている。
彼らは Making Facebook 2x Faster でそれを TTI (Time-to-Interact) と呼んでいる。
We call this metric Time-to-Interact (TTI for short), and it is our best sense of how long the user has to wait for the important contents of a page to become visible and usable. On our homepage, for example, TTI measures the time it takes for the newsfeed to become visible.
いまどきの読み込み時間は、YSlow や Page Speed で簡単に測れるし、内訳をもとに点数も出してくれる。ついその数字を追ってしまうのは人の性だ。そんななかで
- それも大事だけど、この部分をこうすると UX 改善するんじゃないか、と問題を再定義して
- JavaScript でこういうふうにやれば TTI 短くなって UX 良くなるよね、と実装して
- JavaScript がオフでもそれなりに動くようにして (BigPipe が JSON ではなく HTML を返しているのは、このため + DOM が遅いから、だと思う)
- 本番に投入して
- Facebook のあらゆるページで使えるようにして (たとえば、リクルートと提携して出来たという コネクションサーチ も BigPipe を使っている)
と、全部やっていくのを考えると、これはもう、アメリカの回線が遅いからとか、開発者の数が多いからとか、そういう問題じゃないなあと思いました。