HTTP Status Code 103 Early Hintsを試す
HTTP Status Code 103 Early Hints とはWebの読み込みを30%以上高速化させることが期待されている新しいWeb標準のステータスコードです。
OriginがHTTP ステータスコード200を戻すより先に、読み込むべきオブジェクト(cssや画像など)をHTTP ステータスコード 103で戻しブラウザは先に読み込みを開始させます。つまりCDN側のキャッシュ読み込みを、オリジンからCDNにHTTP200が戻るより先に開始させます。
本来これを実装させるためには、オリジンがHTTP ステータスコード103に対応している必要がありますが、Cloudflareの Early Hints機能をオンにすることでHTTPレスポンスヘッダのlink
に設定されているpreload
もしくはpreconnection
を読み取りクライアントブラウザにHTTP103を戻します。
以下の例であれば、クライアントは先にオリジンからCDN、CDNからブラウザにHTTP200が戻るより前にa.png
の読み込みを開始させます。
HTTP/2 103
link: <a.png>; as=image; rel=preload
HTTP/2 200
date: Sun, 09 Jul 2023 11:53:46 GMT
content-type: text/html
last-modified: Sun, 09 Jul 2023 11:42:05 GMT
link: : <a.png>; rel=preload; as=image
accept-ranges: bytes
cf-cache-status: DYNAMIC
server: cloudflare
cf-ray: 7e405e50edde2647-NRT
詳しいフローはこの図を参考にしてください。このブログ記事でその動作がよくまとまっています。
CloudflareではオリジンがHTTP103を戻さなくても、HTTPレスポンスヘッダに含まれているlink: : <a.png>; rel=preload; as=image
を読み取り、先行してHTTP 103としてそのlink
情報、つまりオブジェクトの読み込み先情報を先に戻します。
なおこの機能はHTTP/2移行で動作し、HTTP/1.1では未サポートです。また現在Chrome、Edge、Firefoxがその対応を表明しているものの、ブラウザにはまだ標準実装されておらず、今後数年間かけてスタンダードになると思われます。
やってみる
テストを行うためのオリジンを作ります。Cloudflare Pagesが便利なのですが、このEarly HintsはHTTP200を戻した方が処理が速いと判断される場合は、103ではなく200を戻す性質があり、PagesではHTTP103を再現させることができませんでした。(恐らくCloudflare CDNのキャッシュとオリジンが同じ場所にあることに起因していると予想しますが詳細は不明です・・・すいません)
と、いうことでEC2にnginxをインストールして使います。
sudo dnf install nginx
インストールが終わったらnginxを起動します。
sudo service nginx start
一度デフォルトでアクセスできるか確認しておきます。
sudo service nginx start
cd /usr/share/nginx/html
を実行しhtmlを作成します。
index.html
は以下に置き換えます。a.png
は何でも良いので同じディレクトリにおいておきます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<link rel="stylesheet" href="style.css">
<link rel="preload" href="a.png">
</head>
<body>
<h1>Hello World</h1>
<p>こんにちは、世界!</p>
<img src="a.png"/>
</body>
</html>
ちょうどいい画像が見当たらない場合以下を試してみて下さい
sudo wget https://p.e-words.jp/img/PNG.png
sudo cp PNG.png a.png
nginxのnginx.conf
を以下のように修正します。`/etc/nginxに存在します
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
#Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
location / {
add_header Link: "<a.png>; rel=preload; as=image";
}
}
location / {
add_header Link: "<a.png>; rel=preload; as=image";
}
部分が追記部分です。これによりHTTPレスポンスヘッダにlink: : <a.png>; rel=preload; as=image
が戻るようになり、CloudflareはこれをもとにHTTP103をレスポンスで出力します。
では一度nginxを再起動します
sudo service nginx restart
curl.exe -k -X HEAD -I https:<origin domain>
でアクセスすると以下のようなレスポンスが戻ります。
HTTP/2 200
date: Sun, 09 Jul 2023 12:07:35 GMT
content-type: text/html
last-modified: Sun, 09 Jul 2023 11:42:05 GMT
link: : <a.png>; rel=preload; as=image
accept-ranges: bytes
cf-cache-status: DYNAMIC
server: cloudflare
cf-ray: 7e4072913b27e035-NRT
link: : <a.png>; rel=preload; as=image
が出力されていれば成功です。
DNS Proxyモード設定
ここまでできたらいつも通りDNS ProxyモードをCloudflareで設定します。これによりCloudflare CDN機能が利用可能となります。
ドメイン用管理者画面のSpeed
から最適化
をクリックします。
コンテンツの最適化
タブでEarly Hints
をオンにします。
以上で設定は完了です。
curl.exe -k -X HEAD -I https:<cloudflare domain>
でアクセスを行うと以下のようなレスポンスとなります。
HTTP/2 103
link: <a.png>; as=image; rel=preload
HTTP/2 200
date: Sun, 09 Jul 2023 12:07:35 GMT
content-type: text/html
last-modified: Sun, 09 Jul 2023 11:42:05 GMT
link: : <a.png>; rel=preload; as=image
accept-ranges: bytes
cf-cache-status: DYNAMIC
server: cloudflare
cf-ray: 7e4072913b27e035-NRT
HTTP200より先にHTTP103として画像のパスが戻ってきていることがわかります。
期待通りの動作をしない場合、以下を行ってみて下さい。
- curlを最新版にする。(私の環境では8.0.1では動作せず、8.1.2で動作しました)
- Cloudflareのキャッシュをパージ(削除)し、数回アクセスを行う。
- a.pngを大きい画像に変更して何度か試す
HTTP200を戻してしまった方が早い場合(テスト環境に依存しますがファイルが小さい場合)は103より200が優先されます。
いかがでしょうか。冒頭記載した通り、Chrome、Edge、Firefoxが対応を表明していることもあり、今後SEO観点で重要な機能となるはずです。ぜひ試してみて下さい。
余談
どうしても動作しなかったので、動作に成功した同僚の@yusukebeさんに動いている環境を見せてもらいました。Cloudflare documentでは
link: : a.png; rel=preload; as=image
としてHTTPレスポンスヘッダを戻すようになっていましたが、正しくは <> 付きの以下でした。
link: : <a.png>; rel=preload; as=image
いやー、持つべきものは優秀な同僚ですね(笑) ありがとうございました!
Discussion