Server Side Renderingについて知るべきこと。Server Side Renderingとは何か? それによって何が改善されるのか?(後編) ng-japan 2017
JavaScriptフレームワークとして知られるAngularのイベント「ng-japan 2017」がAngular Japan User Group主催で6月17日に都内で開催されました。
本記事は「Server Side Renderingについて知るべきこと。Server Side Renderingとは何か? それによって何が改善されるのか?(前編) ng-japan 2017」の続きです。
CPU負荷に対する2つの現実解
こうしたCPU負荷に対する現実解としては、生成したHTMLをキャッシュする方法と、above the fold=スクロールしなくても見える範囲だけのHTMLをレンダリングして返す、という方法があります。

しかしこれらは両方とも、諸刃の剣です。
まず、キャッシュに関しては、HTMLを生成したあとでキャッシュすると、CPU負荷は最初のHTMLを生成するところだけで済むので、そのあと何度もリクエストがあったとしても負荷は小さくて済みます。
ただしキャッシュは、いつパージするか、という問題があります。例えば更新頻度の高いコンテンツはキャッシュしても無意味だったりしますし、キャッシュをどこに保存するのかという問題や、そもそも動的なコンテンツはキャッシュできないよね、という課題もあります。

例えば、われわれのサービスではWebページの左上にユーザー名が入るので、そこだけレンダリングしないで返すとか、キャッシュはmemcachedやRedisにキャッシュしても良かったのですが、インメモリキャッシュで済んだのでLRUキャッシュにしました。
この辺は銀の弾丸はないので、それぞれみんなでがんばるしかないと。
もうひとつはabove the foldレンダリング。最初に見える範囲だけServer Side Renderingをして、スクロールしないと見えないところはClient Side Renderingすると。

ただし、見えていないClient Side RenderingのところのSEOが利くかどうかは、最初の話のように保証されていません。
また、Time to Interactive、つまりJavaScriptがロードされて実行されるまでは、スクロールした先の表示が行われないので真っ白な部分が出たりするので、それを許容するかどうか。

このように、それぞれのテクニックをどこまで適用するかは、それぞれのサービス次第というところがあります。
ここまでをまとめると、Server Side RenderingをすればFirst Meaningful Paintまでを高速化できるが、その最適化のためには面倒も多い。
逆に言えば、ちゃんとこれらを実行すれば、First Meaningful Paintまでを高速化しつつ、Single Page Applicationのよいところどりができると思います。
Server Side Rendering不要論への答え
一方で、サーバサイドレンダリング不要論なども世の中にはあります。これらを要約すると、First Meaningful Paintの高速化は捨てて、そのあとのTime To Interactiveまでを高速化すればいいんでしょ、という話かなと思います。

これに対するアンサーとしては、First Meaningful Paintまでの高速化を捨てていいなら、Server Side RenderingはやらなくてもOKだと思っていて、これを捨てられるかどうか。もっと言えば、SEOを捨ててもいいかも含めてですが。

で、First Meaningful Paintを高速化すべきかどうかはサービスの特性に依存するんですよね。僕の会社はリクルートテクノロジーズなのですが、例えばHotpepperで予約している居酒屋がシェアされているとして、そこの居酒屋にいこうとしてポチっとクリックすると、そのタイミングでJavaScripまでロードしてからじゃないとページが表示されないのは遅いと評価されてしまって、それはわれわれのサービスとしては致命的だと思っています。
なのでFirst Meaningful Paintをすごく意識してサービスを作ろうとしています。
それから、これは個人的な話として、パフォーマンスにはあまり妥協したくないんです。

パフォーマンスは積み重ねですし、終わりがなくて、各所でつねに改善の必要があると僕は思っています。
最近のトレンドはFirst Meaningful Paintはもちろん、Time To Interactiveまでの時間が重要になってきていて。
例えばServer Side RenderingでFirst Meaningful Paintがすごく速くなって0.5秒になったとして、でもTime To Interactiveまで5秒だったとすると、そのあいだが4.5秒ある。
ここが離れすぎていると、これはユーザーにとってコンテンツが見えているのに操作できないのでストレスになる。

なので最近はCode SplittingしてなるべくJavaScriptを軽くするとか、HTTP/2のPushをうまく使って次のリソースを事前にキャッシュしておくとか。そうしてTime To Interacitiveまでを高速化する改善策などがでています。このページ(Progressive Web Apps with React.js: Part 2 — Page Load Performance)に書いてあるので、あとで見てみてください。

で、これだけじゃなくて、Navigation StartからFirst Paintまでを速くするにはDBクエリを速くするとかネットワークの改善とかがあるし。

そのあとでFirst Contentful Paaintまでは、CSSでの調整で速くするとか、Loading Indicatorを表示して待たせないように工夫するとか。

初期データをJSONで埋め込むとか、Server Side Renderingをするとか。

画像を遅延読み込みにするとか、効率的なフォーマットにするとか。

JavaScriptの遅延ロードとか。

HTTP/2を利用するとか。

段階ごとにパフォーマンスチューニングのテクニックがあって、それぞれをおざなりにしてはいけないと思って、これをひとつひとつやっていくことで全体のUXが向上すると思うので、今日はこういうお話をしました。
まとめです。

公開されている資料。
あわせて読みたい
ガートナーがIaaS市場を分析したマジッククアドラント2017年版発表。IaaS市場はAWSとAzureが独占しつつあると
≪前の記事
Server Side Renderingについて知るべきこと。Server Side Renderingとは何か? それによって何が改善されるのか?(前編) ng-japan 2017