Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
103 Early Hints
Search
Tatsuki Sugiura
December 13, 2024
Programming
860
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
103 Early Hints
Tatsuki Sugiura
December 13, 2024
More Decks by Tatsuki Sugiura
See All by Tatsuki Sugiura
フロントエンドから触れるHTTPパフォーマンス
sugi_0000
0
24
No more parser-inserted js - defer / async を今こそ完全に理解する
sugi_0000
0
91
FLOSSむかしばなし
sugi_0000
0
28
和暦 & 漢数字 gem
sugi_0000
0
46
FLOSS とフリーカルチャーの流れ
sugi_0000
0
33
Git overview
sugi_0000
0
46
飲む方の茶会
sugi_0000
0
26
Other Decks in Programming
See All in Programming
なぜ型を書くのか? TSKaigi2026で改めて考える #tskaigi_smarthr
kajitack
0
320
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
240
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.3k
分散システム、なんですぐ死んでしまうん?耐障害性を高めたいあなたのためのレジリエンスパターン入門
mshibuya
7
5.5k
フィードバックで育てるAI開発
kotaminato
1
110
これからAgentCoreを触る方へトレンドはGatewayです
har1101
6
480
なぜ関数型プログラミングで「型」と「証明」が語られるのか #fp_matsuri
kajitack
3
770
OS アップデート対応の取り組み方がもっと共有されてほしい
andpad
0
110
【やさしく解説 設計編 #0】DDDのコード、読めるのに分からない人へ
panda728
PRO
2
240
SLOをサービス品質の共通言語にするために 取り組んできたこと
wakana0222
0
450
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
210
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
580
Featured
See All Featured
We Have a Design System, Now What?
morganepeng
55
8.2k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.6k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
1.9k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
290
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
450
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
670
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Utilizing Notion as your number one productivity tool
mfonobong
4
360
Transcript
103 Early Hints 2024-12-13 Tatsuki Sugiura <
[email protected]
> <
[email protected]
>
自己紹介 - Tatsuki Sugiura • 現在 Repro で Booster という
Web サイト高速化 ツールの開発をしています • 個人では RoR を使った開発や和暦gem とか • ESR の 「ハッカーになろう」から OSS活動をはじめる • 過去に OSDN や スラド (/.j) の開発・運営 • お茶が大好きです!
HTTP Status code 1xx 知ってますか? • HTTP のマイナーステータスコード 1xx
• アンケート: どれでもいいので 1xx のコード知ってますか? a. 聞いたことなかった b. なんか聞いた記憶がある・見かけたことがある c. 仕様は読んだことがある d. 実際に使った・もしくはサーバから受け取ったことがある
Status code 1xx について • 実は HTTP Protocol は
リクエスト:レスポンス = 1:1 ではない! • 1xx を使うと1リクエストに対して複数(1+)のレスポンスが返せる • ブラウザ/クライアントはほぼ対応している ◦ とはいえ、エラーにはならないだけで無視する場合も多い • サーバの対応はまちまち • リバースプロキシの対応はかなり微妙
HTTP Status code 1xx の歴史 • 実は HTTP/1.0 (1996) から
1xx に関する記述はある ◦ この頃は “1xx は有効なレスポンスではないが実験的に有用かも” と言うだけ • HTTP/1.1 (1997) で “100 Continue” と “101 Switching Protocols” が規定 ◦ サーバは HTTP/1.0 クライアントに 1xx を送ってはいけない (MUST NOT) ◦ クライアントは 1xx を無視しても良い(MAY)が、エラーにならず受け入れ必須(MUST) ◦ プロキシは 1xx を(例外を除き)クライアントに転送しなくてはならない (MUST) ◦ この時点ではほぼ使われなかったが、WebSocket (2011) で 101 の利用が進む • HTTP/2 (2015) ◦ 101 が非サポートに (多重化を扱えないため) • 103 Early Hints 登場 (2017, RFC 8297)
今回の主題: 103 Early Hints • RFC 8297 (2017 Experimental) •
HTTP/2 server push では実現できなかった、クライアント主導のサブリ ソースリソースの先読みを実現する ◦ Server push では既にキャッシュ済みのデータを送ってしまったりする可能性があり、サ ブリソースの先読みには使いにくかった • その後 HTML Living Standard でも規定 ◦ 互換性の理由から、通常 Early hints は HTTP/2 以上のクライアントに配信される • HTTP/2 h2c や HTTP/1.1 でも一応使えるが、現実的には HTTPS が妥当
具体的にどういう応答? • Link: ヘッダで preload, preconnect などの対象を返す • CSP とも一緒に使える
103 Early Hint Link: </image.png>; rel=preload; as=image 103 Early Hint Content-Security-Policy: style-src: self; Link: </style.css>; rel=preload; as=style 200 OK Content-Type: text/html <!doctype html>... sugi@tempest:~% curl -v http://127.0.0.1:8000/ * Trying 127.0.0.1:8000... * Connected to 127.0.0.1 (127.0.0.1) port 8000 * using HTTP/1.x > GET / HTTP/1.1 > Host: 127.0.0.1:8000 > User-Agent: curl/8.11.0 > Accept: */* > * Request completely sent off < HTTP/2 103 Early Hints < Link: </style.css>;rel=preload;as=style,</script.js>;rel=preload;as =script < < HTTP/2 103 Early Hints < Link: </LCPimage.jpg>;rel=preload;as=image < < HTTP/2 200 OK < Connection: close < Content-Type: text/plain < Hello, World! time is 2024-12-12 10:13:13 +0900 * shutting down connection #0
モデルケース: 伝統的な Web application の処理 DBデータ フェッチ /書き込み /各種処理 リクエスト
time HTML組 み立て HTML返却 cssリクエスト cssリクエスト JavaScript実行 サブリソースの返却 jsリクエスト 画像リクエスト この間クライアントはヒマ HTMLパース jsリクエスト 画像リクエスト
TTFBは伝統的なWebアプリでは意外と長い • Page Speed Insight のしきい値で Good が 800ms •
TTFB までの間、クライアントができることはないのでただ待っている • この間に先にリソースがロードできたらいいよね! というのが Early Hints の動機 • (ただし、SPA や API ベースのサイトの場合はこのモデルに合致しない)
103 Early Hints を使うと DBデータ フェッチ / 書き込み /各種処理 リクエスト
time HTML組 み立て メインリソース HTML返却 cssリクエスト cssリクエスト JavaScript実行 サブリソースの返却 jsリクエスト 画像リクエスト HTMLパース 画像リクエスト jsリクエスト Early Hints Hint を元に prefetch
Cloudflare はこれで 30% サイトを高速化しているらしい https://blog.cloudflare.com/early-hints/
103 Real world example 実際に使われている例 • Shopify • Shopify のサイトならどこで
も試せる • ただ、あまり効果的な指定 ができているわけではなさそ う sugi@tempest:~% curl -o/dev/null -v https://www.mollyjogger.com/ (略) > GET / HTTP/2 > Host: www.mollyjogger.com > User-Agent: curl/8.11.0 > Accept: */* > * Request completely sent off < HTTP/2 103 < link: <https://cdn.shopify.com>; rel=preconnect, <https://cdn.shopify.com>; crossorigin; rel=preconnect < < HTTP/2 200 < date: Fri, 13 Dec 2024 04:02:00 GMT < content-type: text/html; charset=utf-8 (略)
いいじゃん 使おうぜ! と、行きたいところなんですけど……
課題 • 誰が 103 Early Hints を返すのか? ◦ どのサーバが返すのか •
何を Hint として返すのか? ◦ そもそも Hint にする値で妥当なものはなにか? ◦ どうやって妥当なものを見つけるか?
誰が 103 Early Hints を返すのが適切? App server Load
balancer WAF CDN Edge Cache Internal Reverse Proxy 昨今の web アプリのインフラはとても多段に中継されている
App server が 103 を返す App server • メリット: 返すべきリソースの知識は一番持っている、はず?
• 課題: 経路のサーバは全部 103 Early Hint が通るのか? • 課題: 利用しているアプリケーションフレームワークに Early Hints を返す機能があるのか? • 課題: Plain HTTP/1.1 で返すのか? SSL + HTTP/2 を使うのか?
対応状況 (Clients) 対応状況 補足 Chrome ✅ >= 103 HTTP/1.1 での
103 応答は無視する模様 ? Safari ✅ >= 17 Firefox ✅ >= 120 HTTP/1.1 でも可。最初の EarlyHints しか利用しない wget ✅ 単に無視する curl ✅ 単に無視する JavaScript fetch ✅ 単に無視する Ruby net/http ✅ 単に無視する Python http ✅ (⚠) HTTP/1.1 の場合は、最初の 1xx を レスポンスとして扱って しまう
対応状況 (Clients) - 補足 • Firefox は対応していて動くが、devtool 上は特に表示されない ◦ Prelaod
されるリソースは Network tab には普通に出るが、Initiator は as の値になってい る? • Chrome の場合、devtool に別セクションとして表示される https://developer.chrome.com/docs/web-platform/early-hints
対応状況 (App Server / Framework / Lang) 103出力対応状況 補足 Ruby
on Rails ✅ rails >= 5.2.0 –early-hints オプションが必要。puma/falcon/unicorn で対応 NodeJS http ✅ >= 18.11.0 http ライブラリのみ。 express などは対応していない PHP (Apache/fpm) ❌ PHP (FrankenPHP) ✅ Python WSGI ❌ Python ASGI ✅ Extension で対応 Java JakartaEE ✅ >= 5.0.0-M1 Java Tomcat ✅ >= 11.0.0-M23 Rust hyper ❌
• だいたいサーバの Response/Request に専用のメソッドが作られている • Ruby
rack は env['rack.early_hints'] を経由してサーバの機能を呼ぶ API const earlyHintsLink = '</styles.css>; rel=preload; as=style'; response.writeEarlyHints({ 'link': earlyHintsLink }); NodeJS http request.send_early_hints("link" => "</style.css>; rel=preload; as=style,</script.js>; rel=preload") Rails ActionDispatch::Request#send_early_hints
対応状況 (HTTP Server) 対応状況 補足 nginx ✅ 別モジュールで対応 Apache mod_http2
⚠ Server push のバリアントとして対応自体はし ているのだが、as が設定できない? h2o ✅ • 単に設定に書くだけだと、固定値が設定できるだけなので現実的には使えない • 動的にするにはモジュールを書くとか、ビルトインスクリプトを使うなどが必要 • あまり現実的な用途はなさそう
対応状況 (HTTP Proxy) 対応状況 補足 nginx (proxy) ✅ Apache mod_proxy
❌ 1xx は捨ててしまう。最終応答しか中継しない h2o haproxy ✅ Charles ❌‼ エラーになる mitmproxy ❌ 中継せずに捨ててしまう
Edge cache が 103 を返す • メリット: 中継されずに消える心配は無い • メリット:
オリジンに向かうリクエストと同時に 103 をクライアン トに返せば一番早い • 課題: Preload の対象を何らかの手段で渡す必要がある • 課題: もしくはキャッシュや収集した値などを元に決める CDN Edge Cache
対応状況 (CDN) オリジン103の中継 透過キャッシュ 補足 AWS CloudFront ❌ ❌ 単に無視される
Cloudflare ✅ Fastly ⚠ VCLで対応 Akamai Google Cloud CDN すみません、調べきれなかった
Edge cache で 103 に変換する方式 • App server は通常の 200
に preload 用の Link ヘッダをつけて返す • それをキャッシュし、次からは 103 レスポンスとして返却する https://blog.cloudflare.com/early-hints/
誰が 103 Early Hints を返すのか? (再) • 現時点ではオリジンが返すようにする場合、インフラの検討が必要 ◦
Rails などは対応しているが、実際に使うのは大変かもしれない ◦ 中間の中継サーバは意外と対応していない • エッジキャッシュサーバが返すことができる場合は非常に効率が良い ◦ 一方、エッジキャッシュの機能に依存する ◦ 古いデータを返してしまって、無駄な読み込みが発生する可能性は残る
何を 103 Early Hints として返すのか? • Rails のような asset precompile
の仕組みを持っている場合、必須のリ ソースは決定できる • ページごとの LCP 画像も送りたいが、アプリケーションサーバが判断する のは困難なケースも多い ◦ また、アプリケーションサーバが対象を決定するためには、内部の処理が終わってからで ないと分からないケースもある。その場合 103 を出すには遅すぎる。 • クライアントの画面サイズに依存する、js でクリティカルな CSS を差し込 んでいるなど、実際にレンダリングしてみないとわからないケースも多い
何を返すのか? • 絶対使う最低限のアセットだけ指定する • ページをレンダリングしまくるバッチを運用して情報を取り出す • 機械学習などで、HTML/CSS/JS から想定されるリソースを推定できるよう にるする
• 実ユーザのデータを収集して使う
アイデア: 実ユーザのデータを使う • LCP や CSS の情報を別経路で収集する • 集約し、妥当なロード対象を決める •
そのデータを元にエッジキャッシュ(もしく は経路の誰か)が 103 を返却する 103 LCP, CSS…
103 Early Hints は夢があるけど課題も多い • リソースロードの最適化のためには結構効果はありそう • 素直に使えるなら、使いたいところだけど • 実際に適用しようとすると、インフラも対象選択も壁が多い
• 現在 Repro Booster で簡易実現できないか模索中です! ◦ 103 status 自体は使わず、実質同じ事はできないか? ▪ navigate で遷移する直前に js で cache fill を試みる ◦ ロード対象決定のデータ集約を組み込んだサービスを実現したい ◦ 何某か知見をお持ちの方、詳しい方ぜひ色々教えてください!!