世界を動かす技術を、日本語で。

14kbのページは15kbのページよりもはるかに速く読み込むことができる (2022)

概要

  • 小さなWebページ高速表示 が可能
  • TCP slow start アルゴリズムが 14kBの壁 を生む
  • 最初の14kB に重要情報を詰めることが 体感速度向上 の鍵
  • 高遅延環境 では 1ラウンドトリップの遅延 が大きな影響
  • 14kBルール は目安であり、 例外や進化 も存在

TCP slow startと14kBルールの仕組み

  • Webページの容量 が小さいほど 表示速度 が向上
  • 14kBページ15kBページ よりも 最大612ms高速 な場合がある
  • 15kBと16kB の差は ほぼ無視できるレベル
  • この現象の背景には TCP slow start アルゴリズムの存在
  • TCPIP を拡張し、 信頼性の高いデータ転送 を実現
  • HTTP通信 は複数の TCPパケット で構成
  • IP単体 では パケット到達確認機能 がない
  • TCP到達確認(ACK) により 再送制御 を行う

TCP slow startの動作原理

  • サーバー接続直後 にどれだけデータを送れるか 未知
  • 初期送信量 は通常 10 TCPパケット
  • パケットサイズ最大1500バイト (Ethernet標準)
  • ヘッダー40バイト 消費、 実データ1460バイト
  • 10パケット14600バイト(約14kB)
  • 14kB以内 なら 1ラウンドトリップ で全データ送信可能
  • 14kBを超えると 追加ラウンドトリップ が必要

遅延(レイテンシ)の影響

  • ラウンドトリップ遅延ユーザー体感速度 に直結
  • 衛星インターネット では 1往復612ms 以上かかる場合も
  • HTTPS追加で2往復 必要、 合計1836ms の遅延
  • 2G/3G回線・混雑時・不安定なネット ではさらに遅延増大
  • パケットロス が起きると 再送で更なる遅延

14kBルールの活用方法

  • ページ全体14kB以内 に収めるのが理想
  • 圧縮後14kB なので、 非圧縮で約50kB まで可能
  • 重要コンテンツ (CSS/JS/テキスト)を 最初の14kB に配置
  • HTTPヘッダー14kBに含まれる ため注意
  • 画像は極小化 または プレースホルダー 利用推奨

14kBルールの例外と進化

  • 初期ウィンドウ30パケット に拡張されているサーバーも存在
  • TLSハンドシェイクウィンドウ拡大 が可能な場合あり
  • サーバーが経路情報をキャッシュ し、再接続時に多く送信可能なケース
  • HTTP/2 でも 基本的に14kBルールは有効
  • HTTP/3/QUIC14kBルールを推奨

実践的な最適化ポイント

  • 自動再生動画・ポップアップ・トラッキングスクリプト等 は削除
  • 必要最小限のCSS/JS のみを 最初に読み込む設計
  • ファーストビュー (above the fold)に必要な画像のみ読み込み
  • 14kBルール絶対ではなく目安 と認識

参考資料

  • High performance browser networking by Ilya Grigorik
  • Increase HTTP Performance by Fitting In the Initial TCP Slow Start Window by Simon Hørup Eskildsen
  • Critical Resources and the First 14 KB - A Review
  • HTTP3 performance improvements
  • 著者:Nathaniel, 公開日:2022年8月25日, 最終更新:2022年8月26日

Hackerたちの意見

TCPスロースタートが何か知らない人と、ウェブサイトの読み込みが数ミリ秒早くなることを気にするべき人の重なりは、めちゃくちゃ少ないよね。スタートアップは、パフォーマンスよりもまずは立ち上げに集中すべきだし、大企業ならそのレベルのスピード最適化をするための経験豊富なSREチームがいるはずだよ。

大企業ならそのレベルのスピード最適化をするための経験豊富なSREチームがいるはずだよ。ああ、そうだったらいいのに。最近、大企業が開発したアプリケーション見たことある? :)

そうだね。それが、例えばMicrosoftのソフトウェアが完璧に動いて、最高の効率で動作する理由だよ。

同意するよ、そういう風に説明すべきだと思う。でも、Evan WallaceがFigmaを作るときにパフォーマンスにこだわらなかったら、今のFigmaにはなってなかっただろうね。時には、パフォーマンスが機能の一部なんだ。

企業の規模がパフォーマンスや最適化にどう関係あるのか、全然わからない。大きなビジネスがオンラインで何かを迅速に実行してるのをほとんど見たことないよ。

パフォーマンスが重要じゃないって考え方、ほんとイライラする。これがDockerやKubernetes、そして何でも壊す絶対的なスロップスタックを生んだ原因だよ。パフォーマンスは大事だよ。私たちは数十年にわたってKnuthの最適化に関する名言を誤解して、ハードウェアのパフォーマンス向上を5〜6桁も無駄にして、未だに遅くて膨れ上がった欠陥のあるソフトウェアを提供してる。パフォーマンスは実際に重要で、他の条件が同じなら、速い製品の方が遅いのよりも快適だよ。幸いなことに、Figmaの人たちみたいにリスクを取って証明してくれた人たちもいる。たとえ難しい技術的な問題で革新しているとしても(ほとんどの人はそうじゃないけど)、パフォーマンスはやっぱり重要なんだ。

「もっと重要なことに集中してるから気にしない」ってアプローチだと、結局何も気にしなくなるよ。ページロードを最適化してサーバーにアクセスするためのTCPウィンドウサイズに合わせるよりも、会社にとってもっと重要なことは必ずあるからね。だから、最近のほとんどのアプリやウェブサイトは遅くてひどいんだよ。

それに、.exeファイルは無駄が多いって知ってるよね? .comファイルは、実行可能ファイルのサイズを0xFF00h未満に抑えられれば、かなりバイト数を節約できるんだよ(ああ、俺も歳を取ったな)。

それに、a.outフォーマットはelfよりもディスクスペースを節約することが多いけど、実行ファイル間でコードが重複するんだよね。

これを楽しみたいなら、初期ウィンドウ(IW)は送信者によって決まるんだ。だから、サーバーをウェブサイトに合ったパケット数に設定できるよ。こんな感じになると思う:ip route change default via dev initcwnd 20 initrwnd 20。ウェブ検索によると、CDNは今や初期ウィンドウで30パケットになってるから、そこで45kb得られるよ。

悪い市民になって、パケットを1000に設定しちゃえばいいんじゃない?ダイヤルアップ接続の人が詰まる可能性があるくらいで、特にデメリットはないよ。

ウェブ検索によると、CDNは初期ウィンドウで30パケットになってるから、そこで45kb得られるみたい。これについての参考はある?

くそ...俺のホームページは17.2KBだ!(依存関係は含めてないけど) ちなみに、個人のホームページを徹底的に最適化して、Lighthouseのスコアが100/100になったんだ。前はそんなことが可能だなんて思ってもみなかったよ(笑)。Railsで作ったんだけど、サイトを最適化する価値は絶対にあるよ。ページが遅延なしで読み込まれると、本当に気持ちいいからね!

でも、Railsはレンダリングされたページサイズには関係ないよ。完璧なLighthouseスコアおめでとう!

そうそう、news.ycombinator.comが瞬時に読み込まれるのは、脳がすごく喜ぶから、暇な時に自動的に開いちゃうよ。

自分のホームページをチェックしたら、圧縮転送サイズが7.0 kBだったよ。 2.7 kB main.css 2.5 kB favicon.png 1.8 kB

合計 7.0 kB 悪くないと思う! ブログのリストはホームページで生成してるし、他のウェブサイトも自作の静的サイトジェネレーターで作ってるんだ。これはCommon Lispで書いたやつね。 限られた数の数学関連の投稿では、クライアントサイドレンダリングのKaTeXを使ってる。 そんなページでは、KaTeXがなんと347.5 kBも追加されるんだ! katex.min.css 23.6 kB katex.min.js 277.0 kB auto-render.min.js 3.7 kB KaTeX_Main-Regular.woff2 26.5 kB KaTeX_Main-Italic.woff2 16.7 kB

追加合計 347.5 kB いつかKaTeXのサーバーサイドレンダリングも考えた方がいいかも! これは大学の寮にいた頃からのちょっとした情熱プロジェクトなんだ。 HTMLコンテンツ、共通のHTMLテンプレート(ページ間での一貫したレイアウト用)、CSSは全部手書きだよ。 それに、各ページに何を含めるかは保守的に考えてるから、ページが小さく保たれてるんだ。

とはいえ、数学的なコンテンツがある限られたページではクライアントサイドレンダリングのKaTeXを使ってるよ。 MathMLに置き換えるのも試してみては?: https://w3c.github.io/mathml-core/

もう一つのアイデアとしては、最初のページが終わった後に重いライブラリを読み込むってのもありかも。でも、結局は重いままだよね。数式のためにSVGを作って、ビューポートに入ったときに読み込むってのもアリかも。私のちょっとした意見ね。

数学やクライアントサイドのJSを使ったLaTeX表示が理解できないんだよね。なんでこれをHTMLやCSSに事前に計算しておけないの?

これがもう一つの理由かも: https://blog.cloudflare.com/russian-internet-users-are-unabl...

... Cloudflareによる分析では、ロシアのISPによるスロットリングが、インターネットユーザーがウェブ資産の最初の16KBしか読み込めないようにしているため、ほとんどのウェブナビゲーションが不可能になると示唆されている。

その意見には賛成だな。最近の世代は、シンプルな静的ウェブサイトを作るのにNext.jsみたいなフレームワークをデフォルトで使ってるのに気づいた。 それが彼らの基本スタートだよ。 プレーンなHTML + CSS(たまにJSも少し)だけの時代は、悲しいことに消えつつある気がする。

それは納得できるね。 自分もハイパー最適化された、インラインリソース、ブロッキングスクリプトなし、手動で最小化したJS、14KBのウェブサイトを作ったことがあるけど、「ハード」なやり方でやるとデザインとアーキテクチャに縛られちゃうんだ。 要件が変わると、効率的でウェブネイティブに見えたミニマリスティックな選択肢が技術的負債に変わっていく。 みんな「フレームワークなし」を夢見るけど、プロジェクトがもはやおもちゃでなくなるとそうはいかなくなる。 一方で、アイソモルフィックJSフレームワークを使えば、両方手に入るんだ。 コンパイルされたページを出力するものから始めて、パフォーマンスが十分になるように最適化できるし、必要なら厚いクライアントJavaScriptに戻ることもできる。

その気づきはちょっと遅かったかもね。トレンドはもう少し戻ってきてるし。私が扱ったほとんどのフレームワークは静的生成サイトを出せるし、Next.jsもその一つ。Astroはその目的のために最初から設計されてる感じがする。

それに気づいたのは最近なの?jQueryが人気になった2010年前からずっとそうだったよ。

この記事には、個人的に2つの欠陥のある主張があると思う。

  1. 衛星接続で1つのパケットを送るのにかかる時間についての数学がある(約1600ms)。 これは14KBルールの弱い主張で、大きなウェブサイトとの比較がないから。 10パケットが必ずしも16秒かかるわけじゃない。
  2. ウェブページの画像がこの14KBルールに含まれているという言及がある。 画像がページの初期読み込みにインラインされるのはどんな場合? もしこれが特別なケースで、99.9%の画像がそれに従わないなら、少なくとも言及すべきだと思う。

それに、私のユーザーベースが低遅延の衛星接続を使ってるっていう前提もおかしいよね。今の時代、他のどのウェブサイトも数メガバイトあるのに、私のサイトに耐えられないってどういうこと?

どんな場合に画像がページの初期読み込みにインラインされるの?低解像度のサムネイルがCSSフィルターでぼやけて、本物の画像がダウンロード後にフェードインする感じ。ちゃんとやれば、折り返し画像には一枚あたり数百バイトしか追加されないよ。ただ、そんなことをしてるブロガーは多くないと思う。私のブログではやってるけど、たぶんほとんどのブログプラットフォーム(WordpressやMediumみたいな)でも機能としてあると思う。ただ、商業的なフロントエンドのハイパー最適化で、コンバージョンを半パーセントくらい押し上げるためのものだね。

14kBはちょっとハードル高いけど、最初の10パケットにこだわるのはいいアイデアだね。僕が好きなプロジェクトでページサイズに焦点を当ててるのは512kb.clubだよ。[1] これはサイトのページサイズのゴルフスコアみたいなもん。僕のサイト[2]は、追加される前に測ったら71kちょっと超えてた(すべてのアセット含む)。このプロジェクトのおかげでCloudflare Radar[3]も知ったけど、サイト分析やページサイズのための素晴らしいツールがあるんだ。主にインターネットの一般的なダッシュボードだけどね。

当時話題になったこと: 14kbのページは15kbのページよりもずっと速く読み込める - https://news.ycombinator.com/item?id=32587740 - 2022年8月(343コメント)