Chrome、Opera、Yandex ブラウザで使用できる Save-Data
クライアント ヒント リクエスト ヘッダーを使用すると、ブラウザでデータ節約モードを有効にしているユーザーに、より軽量で高速なアプリケーションを配信できます。
軽量版の必要性
ウェブページが軽くて読みやすくなるほど、ユーザー エクスペリエンスが向上し、コンテンツの理解と定着率が上がり、コンバージョンと収益の増加につながることは誰もが同意見です。Google の調査によると、最適化されたページの読み込みは元のページよりも 4 倍速く、使用するバイト数が 80% 少なくなります。これらのページの読み込みは非常に高速になったため、これらのページへのトラフィックも 50% 増加しました。」
2G 接続の数が最終的に減少しましたが、2015 年時点では 2G が依然としてネットワーク テクノロジーの主流でした。3G および 4G ネットワークの浸透と可用性は急速に拡大していますが、関連する所有コストとネットワークの制約は、依然として何億人ものユーザーにとって重要な要因です。
これらはページの最適化に関する説得力のある引数です。
デベロッパーが直接関与せずにサイトの速度を改善する別の方法(プロキシ ブラウザやコード変換サービスなど)があります。このようなサービスは広く利用されていますが、画像やテキストの圧縮が簡単である(場合によっては許容できない)こと、安全な(HTTPS)ページを処理できない、検索結果経由でアクセスしたページのみを最適化する、といった大きな欠点があります。これらのサービスの人気が高いということは、それ自体が、高速で軽量なアプリケーションやページに対するユーザーの需要にウェブ デベロッパーが適切に対応できていないことを示しています。しかしその目標を達成するのは複雑で 困難な道筋です
Save-Data
リクエスト ヘッダー
非常に単純な手法の 1 つは、Save-Data
リクエスト ヘッダーを使用してブラウザにヘルプを与えることです。このヘッダーを特定することで、ウェブページは、コストやパフォーマンスの制約があるユーザーに、最適化されたユーザー エクスペリエンスをカスタマイズして提供できます。
サポートされているブラウザ(下記)では、ユーザーは「データ節約モード」を有効にして、ページのレンダリングに必要なデータ量を削減するための一連の最適化を適用する権限をブラウザに付与できます。この機能が公開またはアドバタイズされると、ブラウザは低解像度の画像をリクエストしたり、一部のリソースの読み込みを遅らせたり、画像やテキストリソースの圧縮など、コンテンツ固有の最適化を適用するサービスを介してリクエストをルーティングすることがあります。
ブラウザ サポート
- Chrome 49 以降では、モバイルで「データセーバー」オプション、またはパソコンのブラウザで「データセーバー」拡張機能をユーザーが有効にした場合に、
Save-Data
がアドバタイズされます。 - Opera 35 以降では、ユーザーがパソコンで [Opera Turbo] モードを有効にしたり、Android ブラウザで [データ削減] オプションを有効にした場合に、
Save-Data
がアドバタイズされます。 - Yandex 16.2 以降は、ターボモードがデスクトップ ブラウザまたはモバイル ブラウザで有効になっている場合に
Save-Data
をアドバタイズします。
Save-Data
設定の検出
ユーザーに簡易的なエクスペリエンスを提供するタイミングを決定するには、アプリケーションで Save-Data
クライアント ヒント リクエスト ヘッダーを確認します。このリクエスト ヘッダーは、転送コストが高い、接続速度が遅いなどの理由でデータ使用量を削減することをクライアントが好むことを示しています。
ユーザーがブラウザで省データ モードを有効にすると、ブラウザはすべての送信リクエスト(HTTP と HTTPS の両方)に Save-Data
リクエスト ヘッダーを追加します。このドキュメントの作成時点で、ブラウザはヘッダー(Save-Data: on
)で 1 つの *on- トークンのみをアドバタイズしますが、将来的には他のユーザー設定を示すために拡張される可能性があります。
また、JavaScript で Save-Data
がオンになっているかどうかを検出することもできます。
if ('connection' in navigator) {
if (navigator.connection.saveData === true) {
// Implement data saving operations here.
}
}
navigator
オブジェクト内に connection
オブジェクトが存在するかどうかを確認することが重要です。これは Network Information API を表します。この API は Chrome、Chrome for Android、Samsung インターネット ブラウザにのみ実装されます。そこから、navigator.connection.saveData
が true
と等しいかどうかを確認するだけでよく、その条件でデータ保存オペレーションを実装できます。
アプリケーションで Service Worker を使用している場合は、リクエスト ヘッダーを検査し、関連するロジックを適用してエクスペリエンスを最適化できます。または、Save-Data
リクエスト ヘッダーでアドバタイズされた設定を探して、代替レスポンス(異なるマークアップ、サイズの小さい画像や動画など)を返すこともできます。
導入のヒントとベスト プラクティス
Save-Data
を使用する場合は、それをサポートする UI デバイスをいくつか用意し、ユーザーが簡単にエクスペリエンスを切り替えられるようにします。たとえば、次のような情報が得られます。Save-Data
がサポートされていることをユーザーに通知し、使用を推奨します。- 適切なプロンプトと直感的なオン/オフボタンやチェックボックスを使用して、ユーザーがモードを識別して選択できるようにします。
- データ節約モードが選択されているときは、そのモードを無効にし、必要に応じて完全なエクスペリエンスに戻すための簡単でわかりやすい方法を提示します。
- 軽量のアプリケーションは、小さいアプリケーションではないことに注意してください。重要な機能やデータを省略するのではなく、発生する費用とユーザー エクスペリエンスをより意識するだけです。例:
- フォト ギャラリー アプリでは、プレビューの解像度を低くしたり、コードを多用しないカルーセル メカニズムを使用したりすることがあります。
- 検索アプリケーションは、一度に返す結果の数を減らしたり、メディア使用量の多い結果の数を制限したり、ページのレンダリングに必要な依存関係の数を減らしたりすることがあります。
- ニュース指向のサイトでは、表示される記事の数を減らしたり、人気の低いカテゴリを除外したり、小さいメディア プレビューを表示したりすることがあります。
Save-Data
リクエスト ヘッダーを確認するサーバー ロジックを用意し、有効になっている場合は代替の軽量なページ レスポンスを提供することを検討します。たとえば、必要なリソースと依存関係の数を減らす、より積極的なリソース圧縮を適用するなどです。Save-Data
ヘッダーに基づいて代替レスポンスを提供する場合は、必ず Vary リスト(Vary: Save-Data
)にそれを追加して、Save-Data
リクエスト ヘッダーが存在する場合にのみこのバージョンをキャッシュに保存して配信する必要があることをアップストリーム キャッシュに伝えます。詳細については、キャッシュの操作のベスト プラクティスをご覧ください。
- Service Worker を使用している場合、アプリケーションでデータ保存オプションが有効になるタイミングは、
Save-Data
リクエスト ヘッダーの有無を確認するか、navigator.connection.saveData
プロパティの値を確認することで検出できます。有効にする場合は、フェッチするバイト数を減らすようにリクエストを書き換えるか、取得済みのレスポンスを使用できるかを検討します。 - ユーザーの接続タイプやテクノロジーに関する情報など、他のシグナルで
Save-Data
を拡張することを検討してください(NetInfo API を参照)。たとえば、Save-Data
が有効になっていない場合でも、2G 接続を使用するすべてのユーザーに軽量のエクスペリエンスを提供できます。逆に、ユーザーが「高速」な 4G 接続を使用しているからといって、ローミング時などに、ユーザーがデータを保存することに関心がないというわけではありません。さらに、Device-Memory
クライアント ヒントでSave-Data
のプレゼンスを強化し、メモリが限られているデバイスのユーザーに適応できます。ユーザーのデバイスメモリもnavigator.deviceMemory
クライアント ヒントでアドバタイズされます。
レシピ
Save-Data
で実現できることは、思い付いたことに限定されます。どのようなことが可能かを理解するために、いくつかのユースケースを見てみましょう。この記事を読んで、他のユースケースが思い浮かぶかもしれません。自由に試して、何が実現できるのか確認してみてください。
サーバーサイドのコードで Save-Data
を確認
Save-Data
状態は JavaScript で navigator.connection.saveData
プロパティを介して検出できるものですが、サーバー側で検出することをおすすめします。JavaScript が実行に失敗することもあります。また、サーバー側の検出は、クライアントに送信される前にマークアップを変更する唯一の方法です。これは Save-Data
の最も有益なユースケースの一部に関係しています。
サーバー側のコードで Save-Data
ヘッダーを検出するための具体的な構文は、使用する言語によって異なりますが、基本的な考え方はどのアプリケーション バックエンドでも同じです。たとえば PHP では、リクエスト ヘッダーは HTTP_
で始まるインデックスの $_SERVER
スーパーグローバル配列に格納されます。つまり、次のように $_SERVER["HTTP_SAVE_DATA"]
変数の存在と値を確認することで、Save-Data
ヘッダーを検出できます。
// false by default.
$saveData = false;
// Check if the `Save-Data` header exists and is set to a value of "on".
if (isset($_SERVER["HTTP_SAVE_DATA"]) && strtolower($_SERVER["HTTP_SAVE_DATA"]) === "on") {
// `Save-Data` detected!
$saveData = true;
}
マークアップがクライアントに送信される前にこのチェックを配置した場合、$saveData
変数に Save-Data
状態が含まれ、ページの任意の場所で使用できます。このメカニズムを図解し、それを使用してユーザーに送信するデータの量を制限する方法の例をいくつか見てみましょう。
高解像度画面に低解像度の画像を配信する
ウェブ上の画像の一般的な使用例として、2 セットの画像を配信することがあります。1 つは「標準」画面用の画像(1 倍)と、高解像度画面(例:Retina ディスプレイ)。この種の高解像度画面は、必ずしもハイエンド デバイスに限定されるものではなく、ますます一般的になっています。アプリのエクスペリエンスの軽量化が望ましい場合は、大きな(2 倍の)バリエーションではなく、低い解像度(1 倍)の画像をこれらの画面に送信する方が賢明かもしれません。Save-Data
ヘッダーが存在する場合にこれを実現するには、クライアントに送信するマークアップを変更します。
if ($saveData === true) {
// Send a low-resolution version of the image for clients specifying `Save-Data`.
?><img src="butterfly-1x.jpg" alt="A butterfly perched on a flower."><?php
}
else {
// Send the usual assets for everyone else.
?><img src="butterfly-1x.jpg" srcset="butterfly-2x.jpg 2x, butterfly-1x.jpg 1x" alt="A butterfly perched on a flower."><?php
}
このユースケースは、送信するデータ量を減らすよう特に要求されているユーザーに対応するための労力がいかに少ないかを示す完璧な例です。バックエンドでマークアップを変更したくない場合は、Apache の mod_rewrite
などの URL 書き換えモジュールを使用して同じ結果を得ることもできます。比較的少ない構成でこれを実現する方法の例があります。
また、<html>
要素にクラスを追加するだけで、このコンセプトを CSS background-image
プロパティに拡張することもできます。
<html class="<?php if ($saveData === true): ?>save-data<?php endif; ?>">
ここから、CSS の <html>
要素で save-data
クラスをターゲットにして、画像の配信方法を変更できます。上の HTML の例に示すように、低解像度の背景画像を高解像度の画面に送信することも、特定のリソースを完全に省略することもできます。
必須ではない画像を省略する
ウェブ上の画像コンテンツの中には、必須ではないものもあります。このような画像はコンテンツの別の面でも役立ちますが、従量制のデータプランですべて活用しようとする場合は望ましくない場合があります。Save-Data
の最も単純なユースケースとしては、前述の PHP 検出コードを使用して、重要でない画像マークアップを完全に省略できます。
<p>This paragraph is essential content. The image below may be humorous, but it's not critical to the content.</p>
<?php
if ($saveData === false) {
// Only send this image if `Save-Data` hasn't been detected.
?><img src="meme.jpg" alt="One does not simply consume data."><?php
}
次の図に示すように、この手法には大きな効果があります。
もちろん、画像を省略できることだけが考えられるわけではありません。Save-Data
を操作して、特定の書体など、他の重要でないリソースの送信を回避することもできます。
必須ではないウェブフォントを省略する
通常、ウェブフォントがページの総ペイロードに占める割合は、画像の場合ほど多くありませんが、依然として広く使用されています。データの消費量もそれほど多くありません。さらに、ブラウザがフォントをフェッチしてレンダリングする方法は想像以上に複雑で、FOIT、FOUT、ブラウザのヒューリスティックなどの概念により、レンダリングが微妙に複雑になります。
無駄のないユーザー エクスペリエンスを求めるユーザーのために、必須ではないウェブフォントを除外した方がよいのは当然のことです。Save-Data
を使用すると、それほど手間がかかりません。
たとえば、Google Fonts の Fira Sans をサイトに追加したとします。Fira Sans はボディコピー フォントとして優れていますが、データを保存しようとするユーザーにとってはそれほど重要ではないかもしれません。Save-Data
ヘッダーが存在する場合に save-data
クラスを <html>
要素に追加することで、最初は必須でない書体を呼び出すスタイルを記述し、Save-Data
ヘッダーが存在する場合はそれを無効にすることができます。
/* Opt into web fonts by default. */
p,
li {
font-family: 'Fira Sans', 'Arial', sans-serif;
}
/* Opt out of web fonts if the `save-Data` class is present. */
.save-data p,
.save-data li {
font-family: 'Arial', sans-serif;
}
この方法では、Google Fonts の <link>
スニペットをそのまま配置できます。ブラウザは、まず DOM にスタイルを適用してから、HTML 要素がスタイルシート内のリソースを呼び出すかどうかを確認することで、CSS リソース(ウェブフォントを含む)を投機的に読み込みます。Save-Data
がオンになっていても、スタイル設定された DOM は呼び出されないため、Fira Sans が読み込まれることはありません。代わりに Arial が有効になります。Fira Sans ほどではありませんが、データプランを伸ばしたいユーザーにとっては望ましい場合があります。
まとめ
Save-Data
ヘッダーは実質的なニュアンスはありません。有効か無効かは問いません。理由にかかわらず、その設定に基づいてアプリが適切なエクスペリエンスを提供するという負担をアプリが負います。
たとえば、ユーザーによっては、接続状況が不安定であってもアプリのコンテンツや機能が失われることが疑われる場合、データ節約モードを許可しないことがあります。逆に、接続状況が良好であっても、ページを可能な限り小さくしてシンプルに保つユーザーもいます。アプリでは、明示的なユーザー操作によって明確な指示がない限り、ユーザーは完全で無制限のエクスペリエンスをユーザーが望んでいると想定することをおすすめします。
サイト所有者およびウェブ デベロッパーは、データおよびコストに制約のあるユーザーのユーザー エクスペリエンスを向上させるために、コンテンツを管理する責任を負います。
Save-Data
の詳細と実用的な例については、ユーザーをサポートするSave Data
をご覧ください。