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
850
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
23
No more parser-inserted js - defer / async を今こそ完全に理解する
sugi_0000
0
91
FLOSSむかしばなし
sugi_0000
0
28
和暦 & 漢数字 gem
sugi_0000
0
45
FLOSS とフリーカルチャーの流れ
sugi_0000
0
31
Git overview
sugi_0000
0
46
飲む方の茶会
sugi_0000
0
25
Other Decks in Programming
See All in Programming
Signal Forms: Beyond the Basics @ngBaguette 2026 in Paris
manfredsteyer
PRO
0
230
RTSPクライアントを自作してみた話
simotin13
0
510
CLIであることを活かしたGitHub Copilot CLI活用術 / GitHub Copilot CLI Pro Tips & Tricks
nao_mk2
1
1.2k
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
150
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
550
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
1.8k
AIエージェントの隔離技術の徹底比較
kawayu
0
470
IBM Bobを活用したレガシーアプリの最新化
oniak3ibm
PRO
1
180
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
0
170
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
3.2k
AIで効率化できた業務・日常
ochtum
0
110
oxlintはeslint/typescript-eslintを置き換えられるのか
shomafujita
2
330
Featured
See All Featured
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
720
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
410
How STYLIGHT went responsive
nonsquared
100
6.2k
WCS-LA-2024
lcolladotor
0
620
Thoughts on Productivity
jonyablonski
76
5.2k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
400
What's in a price? How to price your products and services
michaelherold
247
13k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
BBQ
matthewcrist
89
10k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
530
Six Lessons from altMBA
skipperchong
29
4.3k
For a Future-Friendly Web
brad_frost
183
10k
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 を試みる ◦ ロード対象決定のデータ集約を組み込んだサービスを実現したい ◦ 何某か知見をお持ちの方、詳しい方ぜひ色々教えてください!!