Yakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。
5年弱前投稿

責任ある開発者のためのHTTPヘッダー

安全で、誰にも手頃でアクセスしやすく、ユーザーを尊重したWebを作るためのHTTPヘッダーのプラクティス

原文
HTTP headers for the responsible developer - Twilio (English)
原文著者
Stefan Judis
原文公開日
2019-04-23
翻訳依頼者
D98ee74ffe0fafbdc83b23907dda3665
翻訳者
A3e9a72544c34898bde469ab10cddc25 meiq
翻訳レビュアー
D98ee74ffe0fafbdc83b23907dda3665 doublemarket 907f339337a8fe2a4d4c498d1545231b msh5
原著者への翻訳報告
1782日前 メールで報告済み 編集


This article was originally published on twilio.com, and translated with the permission of Twilio and the author.

当記事の原文はtwilio.comにて公開されたものであり、Twilio社および原著者の許可を得て翻訳しています。


HTTP headers for the responsible developer

この記事は、プレゼンテーション "HTTP headers for the responsible developer" を文章に書き下ろしたものです。スライド、および動画も視聴することができます。


近年、オンラインであることは、多くの人たちにとって当たり前の状態になりました。 誰もがみな、ショッピングやチャット、記事を読んだり目的地への行きかたを検索したりして時間を過ごしています。 Webは私たちと全世界をつなぎますが、確実に言えるのはWebは人と人とをつなぐということです。 私自身はWebを20年使ってきました。そして8年前に開発者になったとき、私とWebの関係に変化が訪れたのです。

開発者は人々をつなぐ。開発者は人々を助ける。開発者は人々に可能性をもたらす。

開発者はあらゆる人々のためのWebを作り上げる力を持ちますが、その力を使うことには責任が伴います。 つまるところ大切なのは、人々を助け、それまでできなかったことを可能にするものを作るということです。

この記事では、人々にとってより良いWebを目指したプロダクトを構築する上で、HTTPヘッダーがどのような助けとなるのかを解説していきたいと思います。

HTTP - Hyper Text Transfer Protocol

まずはHTTPの話をしましょう。HTTPは、コンピューターがWeb上でリクエストやデータを送るのに使われるプロトコルです。

ブラウザがサーバーにあるリソースを要求するとき、HTTPが使われます。 この要求にはkey-valueペアのセットが含まれていて、ブラウザのバージョンや、ブラウザがどんなファイルフォーマットを解釈できるかといった情報を提供します。 このkey-valueペアはリクエストヘッダーと呼ばれます。

サーバーは要求されたリソースとともに応答を返しますが、それだけでなくレスポンスヘッダーを送信し、リソースやサーバーに関する情報を提供します。

Request:
GET https://the-responsible.dev/
Accept: text/html,application/xhtml+xml,application/xml
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7
...

Response:
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Date: Mon, 11 Mar 2019 12:59:38 GMT
...
Response Body

HTTPは現在のWebの基礎であり、ユーザーエクスペリエンスを向上させる様々な方法を提供します。 さあ、どうやってHTTPヘッダーを使えば 安全で、誰にも手頃でアクセスしやすく、ユーザーを尊重した Webが作れるのか、一緒に見ていきましょう。

Webは安全でなければならない

かつて私は、インターネットをブラウズしながら危険を感じるようなことはありませんでした。 けれどもWebについて学べば学ぶほど、心配事が増えてきたのです。 CDNにホストされたライブラリをハッカーが書き換える可能性様々なWebサイトが悪用されて訪問者のブラウザ上で行われる暗号通貨マイニング日常的にソーシャルエンジニアリングしてメジャーなオープンソースプロジェクトに侵入する人々、などという実例を読むことができます。 むろん好ましくはないですが、しかしなぜこういったことを気にかけなければならないのでしょう?

いまの時代Webを構築するのであれば、コードを書くのはあなただけではありません。 最近のWeb開発では、一つのサイトをたくさんの人々の労力が支えています。 あなたはおそらく、多くのオープンソースのコードも利用していることでしょう。 さらには、マーケティング目的のためにいくつかのサードパーティーのスクリプトもインクルードしているかもしれません。 数百もの人々が、あなたのサイトで動くコードを提供しています。 開発者はまず、この現実に対処しなければなりません。

この人たち全員と、書かれたオープンソースのコードを全部信用しなければならないのかって?

いえ、そこらのサードパーティーのコードを信用するのは無理だと思います。 幸いなことに、あなたのサイトを保護し安全にする方法はいくつかあるのです。 加えて、helmetのようなツールはexpressのアプリケーションを保護するのに役立ちます

もし、あなたのサイト上でどれくらいのサードパーティーのコードが実行されるか知りたければ、お好みの開発者ツールのnetworkパネルを見るか、Request Map Generatorを試すとよいでしょう。

HTTPSとHSTS - コネクションを安全に

安全なコネクションは、安全なインターネットの基本です。 HTTPSで暗号化されたリクエストがなければ、あなたのサイトと訪問者のあいだに誰もいないことの確証はとれません。 何者かがサクッとパブリックWifiを立ち上げれば、繋いでくる人に対し中間者攻撃を仕掛けることができます。 あなたは、どのくらいの頻度でパブリックWifiを使いますか? そして、どのくらいの頻度でそのWifiが信頼に足るものか確認していますか?

幸い、いまやTLS証明書は無償で手に入ります。 HTTPSは標準のものとなり、ブラウザベンダーは安全なコネクション下でないと先進的な機能を使えないようにしていますし、HTTPS対応していないWebサイトを安全でないと表示して、HTTPSの導入を促しています。 残念ながら、私たちはいつも安全にWebをブラウズしているわけではありません。 誰かがWebサイトを開こうとして、アドレスバーにプロトコルを入力していなかったら (そもそもなぜ入力しないといけないのかという話がありますが) このアクションは、暗号化されていないHTTPリクエストになります。 安全な運用をしているサイトなら、HTTPSにリダイレクトするでしょう。 けれども、安全でない最初の一発目のリクエストを何者かが傍受していたら?

そこでHSTSレスポンスヘッダー (HTTP Strict Transport Security) を利用すると、当該サイトはHTTPS経由でのみ動作することをブラウザに伝えることができます。

Strict-Transport-Security: max-age=1000; includeSubDomains; preload

このヘッダーは、ブラウザに対しHTTPリクエストを利用したくない旨を伝え、同一オリジンへの後続リクエストでは自動的に安全なコネクションを使うようにします。もう一度同じURLをHTTP経由でアクセスしようとしても、ブラウザはHTTPSを利用し内部的にリダイレクトを行います。

もう一度HTTPを使いたいようなケースのために、この設定をどれくらいの期間有効にするかは max-age で秒単位の設定ができます。 設定をサブドメインにも適用したい場合は includeSubDomains を使えば可能です。

さらにひと手間かけてでも、ブラウザがあなたのサイトを決してHTTPでリクエストしないようにしたければ、preload ディレクティブを設定しグローバルリストにサイトを登録しましょう。あなたのサイトのHSTS設定が最低一年の max-age 要件を満たし、サブドメインでも有効化されていれば、HTTPSでのみ機能するサイトとしてブラウザの内部レコードに保持されるようになります。

ところで my-site.dev のようなローカル環境が、HTTP経由で利用できなくなったのはなぜだか疑問に思ったことはありますか? 実はこの内部レコードこそがその理由で、.dev ドメインが2019年2月に実際のトップレベルドメインになって以来、自動的にこのリストに含まれるようになったためです。

HSTSヘッダーはサイトを少しばかり安全にするだけではなく、高速化も行います。 仮に、誰かが低速なモバイル接続であなたのサイトを訪問しているとしましょう。 もし最初のリクエストがリダイレクトを受け取るHTTPのみであった場合、ユーザーは数秒間何も見えない状態で待たされるかもしれません。 HSTSを使えばこのような無駄な数秒間をなくし、ブラウザが自動的にHTTPSを使うようにできるのです。

CSP - サイトで何が許されているのかを明確に

これであなたのサイトは安全なコネクション下で稼働するようになりましたが、今度はmixed-contentポリシーのために、ブラウザが安全でないアドレスへのリクエストをブロックしはじめる問題にぶつかるかもしれません。 Content Security Policy (CSP)ヘッダーは、このような問題を解決するうえで素晴らしい方法を提供します。 CSPのルールセットは、HTMLのメタ要素かHTTPヘッダーで定義することができます。

Content-Security-Policy: upgrade-insecure-requests

upgrade-insecure-requests ディレクティブは、まるで魔法のように全てのHTTPリクエストをHTTPSにアップグレードするようブラウザへ伝えます。

CSPは、ただのプロトコルではありません。 あなたのサイト上でどのようなリソースやアクションが許されているかを定義する上で、個々の粒度でできる設定方法を提供します。 たとえば、どのスクリプトが実行されるべきかとか、画像はどこからロードされるべきか、といったことを定義することができます。 もし許可されていないことが行われようとすればブラウザはブロックし、あなたのサイトを潜在的な攻撃から守ります。

CSP log

いまこれを書いている時点では、CSPには24種類の設定オプションがあります。 これらのオプションは、スタイルシート上でのスクリプト使用からService Workerのオリジンに至るまで多岐にわたります。


CSP options

完全な概要はMDN上で見ることができます


CSPを使うと、サイトが何をインクルードすべき/すべきでないのかを明確にすることができます。

Content-Security-Policy: default-src 'self'; script-src 'self' just-comments.com www.google-analytics.com production-assets.codepen.io storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: images.contentful.com images.ctfassets.net www.gravatar.com www.google-analytics.com just-comments.com; font-src 'self' data:; connect-src 'self' cdn.contentful.com images.contentful.com videos.contentful.com images.ctfassets.net videos.ctfassets.net service.just-comments.com www.google-analytics.com; media-src 'self' videos.contentful.com videos.ctfassets.net; object-src 'self'; frame-src codepen.io; frame-ancestors 'self'; worker-src 'self'; block-all-mixed-content; manifest-src 'self' 'self'; disown-opener; prefetch-src 'self'

上記のルールセットは私の個人サイトで使っているものですが、もしこのCSP定義の例を考えつくのはかなり難しいように思えたとしたら、全くもってその通りです。 このCSPルールセットを自分のサイトで実装するにあたり、正しく機能させるまでに3回は試行錯誤する必要がありました。 ルールセットのせいでサイトが何度か壊れてしまったので、デプロイしてはロールバックを繰り返したものです。 しかし実は、もっと良い方法が存在します。

サイトが壊れるのを防ぐために、CSPにはレポートのみを行うオプションがあります。

Content-Security-Policy-Report-Only: default-src 'self'; ... report-uri https://stefanjudis.report-uri.com/r/d/csp/reportOnly

Content-Security-Policy-Report-Only モードを利用すると、ブラウザはブロックされる見込みのリソースのコンソールログ出力だけを行います。 このレポートの仕組みはルールセットの動作確認と調整に役立ちます。

Content-Security-PolicyContent-Security-Policy-Report-Only の二つのヘッダーは、ルール違反とログ情報を report-uri へ送信するエンドポイントの定義手段を提供します。 ログ出力用のサーバーをセットアップすれば、送信されたログ情報を使って、リリースする準備ができるまでCSPルールの微調整を行うことができます。

おすすめの手順は、まずCSPをレポートモードだけでデプロイし、本物のトラフィックからどんな違反が入ってくるかを分析し、あなたの制御下にあるリソースに対する違反が出てこない場合にだけ、設定を有効にすることです。

もしこのようなログを扱うためのサービスをお探しなら、私はReport URIを使っていますが、とても役に立っています。

CSPの普及状況

近年のCSPのブラウザサポート状況は良好ですが、残念なことに利用しているサイトはそれほど多くありません。 どれくらいの数のサイトがCSPとともにコンテンツを配信しているかを調べるため、HTTP Archiveにクエリを投げてみたのですが、クロールされているサイトのうちCSPを利用しているものはわずか6%しかありませんでした。 私たちはWebをより安全な場所にするためにもっとうまくやれることがあると思いますし、ユーザーが気づかないうちに暗号通貨のマイニングをさせられるようなことも避けられるはずです。

CSP ratio

Webは手頃でアクセスしやすいものでなければならない

この記事を書いているあいだ、私は高速なWifi接続を利用した比較的新しいMacBookの前に座っています。 開発者は、このような環境が大多数のユーザーにとって当たり前ではないのだということを、しばしば忘れてしまいがちです。 私たちのサイトを訪問する人たちは、古い電話端末に貧弱な接続環境を使っています。 数百ものリクエストで重たく膨れ上がったサイトは、彼らに対し好ましくないエクスペリエンスを提供してしまいます。

それにエクスペリエンスの話だけではありません。人々はどこに住んでいるかによって、データに対し支払う金額が異なります。 仮に、自分が病院のWebサイトを構築していると想像してみてください。 まさにこのサイト上の情報が、ときに決定的なものとして、人々の命を救うかどうかを左右するかもしれないのです。

病院サイトでの1ページが5MBもあると、サイトは低速になるばかりでなく、本当に必要としている人たちにとって高価になりすぎてしまう可能性があります。 ヨーロッパやアメリカ合衆国における5MBの値段は、アフリカでの5MBのデータに対する値段とは比べ物になりません。 開発者には、Webを誰にも手頃でアクセスしやすいものに保つ責任があります。 この責任には、適切なリソースを配信することや、妥当なツールを使うための評価 (ランディングページにJavaScriptフレームワーク、本当に必要ですか?) そして不要なリクエストを避けることが含まれます。

Cache-Control - 変更されていないリソースへのリクエストを避ける

最近のWebサイトは、スタイルシートからスクリプトのファイル、そして画像に至るまで、容易に数百にもなるリソースを内包します。 Cache-Control ヘッダーを使うと、開発者はリソースをどのくらいの期間「十分新しい」とみなし、ブラウザキャッシュから提供しても差し支えないと考えられるかを定義できます。

Cache-Control: max-age=30, public

適切な Cache-Control の設定を行うとデータ転送は抑えられ、ファイルは max-age で指定された一定秒数の間、ブラウザキャッシュから利用することができます。 定められた時間が経過したら、ブラウザはキャッシュされたリソースを再検証することになります。

しかし訪問者がページを再読み込みした場合は、キャッシュされたデータがいまだに有効かどうかを確かめるべく、ブラウザは参照されているリソースを含めて再検証を行います。 サーバーはキャッシュされたデータがまだ良好であることを示す304応答を返すか、更新されたデータを配信しつつ200応答を返します。 これは転送データ量の削減にはつながりますが、必要に応じて行われたリクエストとは言えません。

そこで役に立つのが immutable の機能です。

immutable - 同じリソースは二度とリクエストしない

モダンなフロントエンドのアプリケーションでは、通常スタイルシートとスクリプトファイルは styles.123abc.css のような、ユニークなファイル名を持っています。 このファイル名は特定のファイルの中身によって決まります。 もしファイルの中身が変われば、異なるファイル名がつけられます。

このようなユニークなファイルは、ユーザーがページを再読み込みしたときを含め、いつまでもキャッシュされてしまう可能性があります。 immutableの機能は、ブラウザに対し一定期間のあいだリソースを再検証しないように伝えることができます。 これは変更されることのない固有の資産を扱うとき、再検証のリクエストを避ける上で有意義なものです。

Cache-Control: max-age=31536000, public, immutable

最適化されたキャッシュのやりかたは非常に難しく、特にブラウザでのキャッシュには複数の設定方法が提供されており、あまり直感的ではありません。以下のリソースを参照することをおすすめします。

Accept-Encoding - 最大限まで圧縮する (えっと... 最小限か)

Cache-control を利用すると、リクエストの回数、および繰り返しネットワーク上を行き交うデータ量を削減できるのを見てきましたが、私たちはリクエスト数を減らせるだけではなく、転送されるもの自体を小さくすることもできます。

リソースを配信するとき、開発者はできる限り小さなデータを送るよう心がけなければなりません。 HTMLやCSS、JavaScriptのようなテキストベースのリソースでは、転送されるデータ量を減らす上で、圧縮が重要な役割を果たします。

近年、もっとも良く使われている圧縮はgzipです。 サーバーはテキストファイルをその場で瞬時に圧縮できるくらい高速ですし、リクエストに応じて圧縮されたデータを提供することもできます。 けれども、いまやgzipはベストな選択肢ではありません。

ブラウザが行なっているHTMLやCSS、JavaScriptといったテキストベースのファイルに対するリクエストを調べ、リクエストヘッダーを見てみると accept-encoding ヘッダーが見つかるでしょう。

Accept-Encoding: gzip, deflate, br

このヘッダーは、サーバーがどんな圧縮アルゴリズムを解釈するかを伝えます。 さほど良く知られていない brBrotli圧縮のことで、GoogleやFacebookのような高トラフィックのサイトで利用されています。 Brotli圧縮を使うには、サイトはHTTPSで稼働している必要があります。

この圧縮アルゴリズムは、小さなファイルサイズを目標に作られたものです。 ローカルマシン上で手動でのファイル圧縮を試してみると、実際Brotliはgzipよりも優れた圧縮ができることが分かるでしょう。

br vs gzip

もしかすると、Brotli圧縮は低速だと聞いたことがあるかもしれません。 その理由は、Brotliには11種類の圧縮モードがあり、長いエンコーディング時間をかけてでも小さなファイルサイズを保証することを優先した結果、デフォルトモードが選択されるためです。 一方のgzipには9種類のモードがあり、デフォルトモードはスピードもファイルサイズも考慮に入れて選択されます。

このような判断のため、Brotliのデフォルトモードはデータ伝送時の圧縮に用いるには不向きですが、圧縮モードを変更すると、gzipと遜色ないスピードで小さなファイルサイズを実現することができます。そうすればBrotliをデータ伝送時の圧縮に使うこともできますし、サポートされているブラウザに対してはgzipの代替に相当するものとして扱える可能性もあるでしょう。

加えて最大限にファイルサイズを削減したいのであれば、動的にファイルを圧縮する考えはやめて、zopfliを利用して最適化されたgzipファイルやBrotliファイルを事前生成して、静的に配信する方法もあります。

さらにBrotli圧縮について読み、gzipと比べてどのようなものかを知りたければ、Akamaiの人たちがこのテーマで発展的な研究をしています。

AcceptとAccept-CH - ユーザーに特化したリソースを提供

テキスト資産を最適化すると何KBものファイルサイズを抑えられるのは素晴らしいことですが、もっと重たい画像のようなリソースでさらに大きなデータを削減するにはどうしたら良いのでしょうか?

Accept - 適切なフォーマットで画像を配信

ブラウザは、どんな圧縮アルゴリズムを解釈するかを教えてくるだけではありません。 ブラウザが画像をリクエストするときは、どんなファイル形式を解釈できるかの情報も提供しています。

Accept: image/webp, image/apng, image/*,*/*;q=0.8

ここ数年、新しい画像フォーマットを巡る競争が行われてきましたが、どうやら webp が勝者のようです。 webpはGoogleによって開発された画像フォーマットであり、最近ではwebp画像はかなり広くサポートされています。

このリクエストヘッダーを使うと、たとえブラウザからは image.jpg がリクエストされたときであっても、開発者はよりサイズの小さな webp 画像を配信するようにすることができます。 Dean Humeは、Service Workerでこれを実現する方法について優れたガイドを書いています。すごく良いですね!

webp

Accept-CH - 適切なサイズの画像を配信

サポートしているブラウザに対しては、クライアントヒントを有効にすることもできます。 クライアントヒントは、viewportの幅や画像の幅、さらにはRTT(round trip time)や 2g の接続方式のようなネットワークの条件の追加ヘッダーを送信するよう、ブラウザに伝える方法です。

このような設定はメタ要素の追加によって有効化することができます:

<meta http-equiv="Accept-CH" content="Viewport-Width, Downlink">
<meta http-equiv="Accept-CH-Lifetime" content="86400">

あるいは、最初のHTMLリクエスト時にヘッダーを設定してもよいです:

Accept-CH: Width, Viewport-Width
Accept-CH-Lifetime: 100

サポートしているブラウザは、後続のリクエストでは定義された時間の長さ (Accept-CH-Lifetime の秒数) に関する追加情報を送信するようになり、開発者がHTMLを変更することなしにユーザーの状況に合わせた画像を用意してくれます。

たとえば画像の幅の追加情報をサーバーサイドで受け取れるようにするには、画像に sizes 属性をつけ、この画像がどのようにレイアウトされるのかをブラウザに伝えるようにしましょう。

<!-- この画像はフル幅、すなわち100 viewport width (vw)で表示されます -->
<img class="w-100" src="/img/header.jpg" alt="" sizes="100vw">

最初の段階で Accept-CH レスポンスヘッダーと sizes 属性のついた画像を受信すれば、サポートしているブラウザは viewport-widthwidth ヘッダーを画像へのリクエストに含め、どんな大きさの画像が最適かをサーバー側に教えてくれます。

viewport-width

サポートされた画像フォーマットと寸法があれば、エラーが起きないようファイルフォーマットやサイズに気を遣った以下のような画像要素を繰り返し書かなくとも、ユーザーに合わせて作られたメディアを送信することができます。

<picture>
  <!-- Chrome, Edge, Firefox, Operaにはwebp画像を配信する -->
  <source
    media="(min-width: 50em)"
    sizes="50vw"
    srcset="/image/thing-200.webp 200w, /image/thing-400.webp 400w,
        /image/thing-800.webp 800w, /image/thing-1200.webp 1200w,
        /image/thing-1600.webp 1600w, /image/thing-2000.webp 2000w"
    type="image/webp">
  <source
    sizes="(min-width: 30em) 100vw"
    srcset="/image/thing-crop-200.webp 200w, /image/thing-crop-400.webp 400w,
        /image/thing-crop-800.webp 800w, /image/thing-crop-1200.webp 1200w,
        /image/thing-crop-1600.webp 1600w, /image/thing-crop-2000.webp 2000w"
    type="image/webp">
  <!-- 他のブラウザにはjpeg画像を配信する -->
  <source
    media="(min-width: 50em)"
    sizes="50vw"
    srcset="/image/thing-200.jpg 200w, /image/thing-400.jpg 400w,
        /image/thing-800.jpg 800w, /image/thing-1200.jpg 1200w,
        /image/thing-1600.jpg 1600w, /image/thing-2000.jpg 2000w">
  <source
    sizes="(min-width: 30em) 100vw"
    srcset="/image/thing-crop-200.jpg 200w, /image/thing-crop-400.jpg 400w,
        /image/thing-crop-800.jpg 800w, /image/thing-crop-1200.jpg 1200w,
        /image/thing-crop-1600.jpg 1600w, /image/thing-crop-2000.jpg 2000w">
  <!-- 画像をサポートしないブラウザのためのフォールバック -->
  <img src="/image/thing.jpg" width="50%">
</picture>

viewportの幅と画像サイズにさえアクセスできれば、資産をリサイズするロジックをサーバー側処理の真ん中に据えることも可能です。

しかし考えなければならないのは、正確な画像の幅が分かるからといって、毎回全ての幅に合わせた画像を作りたいわけではないことです。 特定の寸法の幅に合わせた画像 (image-200, image-300...) を送ることは、CDNのキャッシュを活用し、計算時間を削減することにつながります。

さらには、Service Workerのような最近の技術があれば、クライアント側に介入してリクエスト自体を変更し、最も適した画像ファイルを提供することもできます。クライアントヒントが有効化されたService Workerがあれば、レイアウト情報へのアクセスとともにCloudinaryのような画像APIを利用することができ、適切なサイズの画像を受け取れるようブラウザ内で画像URLを調整することができるでしょう。

さらにクライアントヒントに関する情報をお探しなら、Jeremy Wagnerの記事か、Ilya Grigorikの記事を読むと良いでしょう。

Webは人々を尊重するものでなければならない

1日のうち何時間もの時間をオンラインで過ごす私たち全員にとって、私がすごく重要だと思う最後の側面、それはWebが人々を尊重するものでなければならないということです。

preload - 待ち時間を短縮

開発者として、ユーザーの時間は大切にしたいものです。 時間を無駄にしたい人は誰もいません。 これまでのセクションで議論してきたように、適切なデータを配信することは、かかる時間やデータ量を減らす上で大きな役割を果たします。 それには何に対するリクエストが行われるかだけでなく、タイミングや順番も関わってきます。

例を考えてみましょう。 サイトでスタイルシートをインクルードすると、読み込みが済むまでブラウザでは何も見えません。 ブラウザは、何も表示していないあいだもHTMLをパースし続け、取ってくる必要のある他のリソースを探します。 スタイルシートが読み込まれてパースされると、今度はフォントのように、他にもリクエストが必要になるクリティカルなリソースが含まれているかもしれません。 このように連続したプロセスは、訪問者からみた読み込み時間を増やしてしまいます。

rel=preload を使うと、これからどのようなリソースがリクエストされるのかの情報をブラウザに伝えることができます。

リソースはHTML要素でプリロードすることができます。

<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin="anonymous">

もしくは、ヘッダーでも。

Link: </font.woff2>; rel=preload; as=font; no-push

このようにするとブラウザは、ヘッダーを受信するか link 要素を発見すると、必要になった時にブラウザキャッシュに載せておけるよう、すぐにリソースへリクエストを行います。 このプロセスは、訪問者の時間に価値を置くものです。

リソースを最善の方法でプリロードし、設定内容についてくまなく理解するには、以下の情報を参照することをおすすめします:

Feature-Policy - イラっとさせる人にならないように

仮に、もう私が見たくないものを一つだけ挙げるとすれば、それは問答無用でいちいち許可を求めてくるWebサイトです。 私の同僚、Phil Nashの言葉から引用すれば十分でしょう。

ページの読み込み時に通知許可を要求するな。

開発者は人々に敬意を払い、訪問者をイライラさせるようなサイトを作ってはいけません。 人々は許可を求めるダイアログを片っ端からクリックするわけです。 Webサイトや開発者は相当な信用を失いますし、輝かしいあらゆるWebの新機能も、開発者が配慮して利用しなければその力を失ってしまいます。

しかし、大量のサードパーティーのスクリプトをサイトにインクルードすることが必須で、これらのスクリプト群が次から次へと許可を求めるダイアログを出してくるような場合、どうしたら良いのでしょう? インクルードされた全てのスクリプトの振る舞いを、いかにして知ることができるでしょうか?

こんなときが Feature-Policy ヘッダーの出番です。 このヘッダーを使うと何の機能が許可されるのかを定義でき、サイトで実行される他者のコードが引き金となって現れる、許可を求めるダイアログのポップアップを制限することができます。

Feature-Policy: vibrate 'none'; geolocation 'none'

これはヘッダーを使って定義することもできますし、サードパーティーの統合でありがちな、iframeのように埋め込みをするコンテンツでも定義することができます。

< iframe allow="camera 'none'; microphone 'none'" >

いまこれを書いている段階で Feature-Policy はまだかなり実験的ではあるものの、このさき追加されるオプションを見てみると、とてもワクワクできる内容です。 そう遠くない未来に、開発者はイラっとくるダイアログを防げるだけでなく、最適化されていないメディアをブロックできるようになる可能性があります。 このような機能は、ユーザーエクスペリエンスに大きな差をつけるでしょう。


Feature-Policy

Feature-Policyに関する一連の概要はMDN上にあります。


上のfeature policyのリストを見ると、一番やっかいなプッシュ通知はどうなるのか気になるかもしれません。 いざやってみると、思いのほか Feature-Policy の実装は難しかったようです。 さらに知りたければ、GitHubのissueを追ってみるとよいでしょう。

feature policyを使うと、図らずもあなたやサードパーティーにより、サイトが許可要求ブロック祭りと化してしまうのを防ぐことできます。 残念ながら最近の多くのサイトでは、それが普通の状態になってしまっているのですが。

Webはあらゆる人のためのものでなければならない

この記事では、ユーザーエクスペリエンスの改善に役立ついくつかのヘッダーを紹介したにすぎません。 ほぼ網羅されたヘッダー群の概要とその可能性について知りたければ、Christian Schaeferのスライド “HTTP headers – the hidden champions” がおすすめです。

いまの時代、素晴らしいWebサイトを作るのは困難なことだと思います。 開発者はデザイン、デバイス、フレームワーク、それから... そうです。ヘッダーがどんな役割を果たすのかを考えなければいけません。 願わくばこの記事が、あなたが次のWeb開発のプロジェクトで、安全性や手の届きやすさ、ユーザーを尊重することについて考えるきっかけになることを望みます。 なぜならそういった要因こそが、Webを本当の意味で誰にとっても素晴らしくするものだからです。


筆者にコンタクトしたい場合は、以下からどうぞ:

次の記事
モノリポによって得られる多くの恩恵
前の記事
あらゆるデータセットに使える3つの可視化テクニック

同じタグの付いた翻訳済み記事
UI/UX

Feed small 記事フィード

新着記事Twitterアカウント