直感に反する解決策:CSSの配信量を増やす
GitHubは最近、特定のターゲットページにおいてサーバーのレンダリング時間を最大22%短縮するという大きな成果を報告しました。このパフォーマンス向上は、「より多くのCSSを配信する」という直感に反する決断から生まれました。GitHubは、スタイルをオンザフライで動的に生成するのではなく、ビルド時にスタイリング作業をコンパイルし、リクエスト処理時に発生するCPU負荷の高いタスクをオフロードすることを選択しました。
この結果は、多くのWeb開発者にとって逆行しているように聞こえるかもしれません。従来の通説では、パフォーマンスのためにはルートごとに最適化された軽量なCSSが理想的であるとされています。しかし、特にサーバーサイドでレンダリングされるCSS-in-JSライブラリを使用してこの調整済みCSSを動的に生成すると、ユーザーからのリクエストごとにサーバーのCPUサイクルを大幅に消費する可能性があります。「必要な」CSSのみを送信するという一見のメリットが、サーバーサイドのボトルネックとなってしまうのです。
重要な点として、この改善は「サーバーサイドレンダリング」のみに焦点を当てています。22%という数値は、サーバーが最初のHTMLレスポンスを準備するために節約された時間を表しています。これは、クライアントサイドのページ読み込み時間が同じ割合で短縮されたことや、アプリケーション全体が22%高速化したことを意味するものではありません。これはサーバーのワークロードに対するターゲットを絞った最適化であり、スタイリングロジックの大部分を実行時の処理から静的アセットのコンパイルへと移行させたものです。
実行時のスタイリングに隠されたCPUコスト
GitHubの初期のアーキテクチャは、サーバーサイドでレンダリングされるCSS-in-JSに大きく依存していました。これは、リクエストごとにスタイリングロジックを実行する手法です。このアプローチでは、JavaScriptを活用してプロップ依存のスタイルを評価し、一意のクラス名を生成し、サーバーがHTMLをレンダリングする際に必要なCSSを収集します。一見効率的に見えますが、この動的なプロセスには隠れた計算コストが存在します。
コンポーネントが多用されるページでは、このコストが劇的に増大します。各コンポーネントのスタイル解決と挿入は、すでに混雑しているレンダリングパスにCPU負荷を追加します。何百ものコンポーネントが存在し、それぞれが独自のスタイル評価をトリガーする可能性があるページを想像してみてください。その累積的な影響は、すぐにサーバーの大きなボトルネックとなります。
実行時のスタイリングには、特定のページ状態に必要なスタイルのみを出力し、クライアント側のCSSペイロードを最小限に抑えるという魅力的な利点があります。しかし、この選択性には代償が伴います。サーバーは、すべての着信リクエストに対して同じスタイル計算と文字列操作を繰り返し実行するというCPUサイクルのコストを支払うことになります。
このトレードオフはGitHubにとって明らかでした。クライアントバンドルを軽量化するという約束は、サーバーのレンダリング時間が増大するという事実に影を潜め、彼らはパフォーマンスの低下が動的でコンポーネント駆動型のスタイリングという利点に見合うものなのかを再評価せざるを得なくなりました。
CSS Modulesによるリクエスト前の処理
GitHubがCSS Modulesへ移行したことは、計算処理がどこで行われるかという根本的な転換を象徴しています。スタイルをオンデマンドで生成する代わりに、CSS Modulesはビルド時にスタイルを静的な.cssファイルにコンパイルします。つまり、サーバーは定義済みのクラス名を持つ静的なHTMLのみをレンダリングするため、リクエスト・レスポンスのサイクルからスタイル生成の処理を完全に切り離すことができます。
これは作業を排除するのではなく、そのコストをシフトさせるものです。より多くのCSSを配信することは、クライアントにとって初期ペイロードがわずかに増加することを意味するかもしれませんが、これらの静的ファイルは非常にキャッシュ効率が高く、サーバーのCPUは実行時のスタイル評価という集中的なタスクから解放されます。このトレードオフは、サーバーのパフォーマンスと初期レンダリング時間の短縮を優先したものです。
特定のGitHubページで報告されたサーバーレンダリング時間の22%短縮は説得力のある結果ですが、これをプラットフォーム全体に共通する向上と混同しないことが重要です。GitHubのより広範なPrimer移行では、6,400以上の動的プロップが非推奨となり、主要コンポーネントスイート全体でサーバーサイドレンダリング時間が55%、コンポーネントの初期化時間が25%削減されました。
ページごとの向上率は1%から22%と幅があり、アプリケーションの複雑さと規模を反映しています。この微妙な結果は、処理をビルド時に移行するという原則は妥当であるものの、正確なパフォーマンス上の利点はアプリケーション独自のアーキテクチャやコンポーネントの使用状況に大きく依存することを示しています。このアーキテクチャの変更に関する詳細は、Improving site performance by shipping more CSS - The GitHub Blog を参照してください。
この記事が気に入ったら、毎朝同じようなものをメールで受け取れます。
1日1通 · 2クリックで解除 · サードパーティのトラッキングなし
スタイリングの思想ではなく、ページを測定せよ
GitHubの調査結果は重要な教訓を与えてくれます。それは、スタイリングの思想ではなくページを測定せよということです。チームは、サーバーレンダリング時間をCSSバイト数、キャッシュ動作、そしてTime to First Byte (TTFB)やLargest Contentful Paint (LCP)といったユーザー体験に関わる重要な指標と併せて、代表的なルート上で評価する必要があります。この全体的な視点こそが、ユーザー体験への真の影響を明らかにします。
唯一無二のスタイリングソリューションは存在しません。CSS Modules、Tailwind CSS、Chakra UI、そしてゼロランタイムツールは、それぞれオーサリング体験、ネットワークペイロード、アーキテクチャのオーバーヘッドにおいて異なるトレードオフを提示します。選択は普遍的な決定ではなく、アプリケーションの特定のニーズとパフォーマンスのボトルネックに完全に依存します。
ユーザーの全行程をベンチマークすることが極めて重要です。GitHubはより多くのCSSを出荷することでサーバーレンダリング時間を最大22%短縮しましたが、これだけでページ全体の読み込みが高速化されるとは限りません。サーバーは連鎖の一部に過ぎず、クライアント側のペイロードが重くなったりネットワーク環境が遅かったりすれば、サーバー側の利点が打ち消される可能性があります。
最終的な目標は、エンドユーザーにとってより高速で応答性の高いアプリケーションを実現することです。そのためには、包括的な指標セットに対してスタイリングモデルを厳密にテストし比較する必要があります。アプリケーションのアーキテクチャに最適で、フルスタック全体で実証可能な改善をもたらすアプローチを選択してください。
よくある質問
GitHubはどのようにしてサーバーレンダリング時間を22%短縮しましたか?
特定のターゲットページにおいて、GitHubはランタイムのCSS-in-JSからビルド時のCSS Modulesへ移行することで、サーバーサイドのスタイリング処理を削減しました。
サーバーレンダリングが22%高速化されることは、ページが22%高速化されることを意味しますか?
いいえ。それはサーバーレンダリング時間について述べているだけで、合計読み込み時間ではありません。ネットワーク転送、CSSの解析、レンダリングもユーザーが体験するものに影響を与えます。
なぜランタイムのCSS-in-JSはサーバーレンダリングを遅くする可能性があるのですか?
サーバーはリクエストごとにレンダリングを行う際、動的なスタイルの評価、クラス名の生成、CSSの収集や挿入を行う必要があるためです。
チームはいつCSS Modulesを検討すべきですか?
サーバーサイドでのスタイル生成にコストがかかり、チームがスコープ付きスタイルを重視する場合に適していますが、CSSペイロードは測定されるべきです。

