Chrome、Opera、Yandex の各ブラウザで利用可能な Save-Data Client Hints リクエスト ヘッダーを使用すると、デベロッパーは、ブラウザでデータ節約モードを有効にしているユーザーに、より軽量で高速なアプリケーションを提供できます。
軽量なページの必要性

ウェブページの読み込みが速く、軽量であるほど、ユーザー エクスペリエンスの満足度が高まり、コンテンツの理解と定着が促進され、コンバージョンと収益が増加することは、誰もが認めるところです。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 Client Hints リクエスト ヘッダーをチェックして、ユーザーに「ライト」エクスペリエンスを提供するタイミングを判断できます。このリクエスト ヘッダーは、転送コストが高い、接続速度が遅いなどの理由で、データ使用量を削減したいというクライアントの要望を示します。
ユーザーがブラウザでデータ節約モードを有効にすると、ブラウザは Save-Data リクエスト ヘッダーをすべての送信リクエスト(HTTP と HTTPS の両方)に追加します。この記事の執筆時点では、ブラウザはヘッダー(Save-Data: on)で 1 つの *on- トークンのみをアドバタイズしますが、今後、他のユーザー設定を示すように拡張される可能性があります。
また、JavaScript で Save-Data が有効になっているかどうかを検出することもできます。
if ('connection' in navigator) {
if (navigator.connection.saveData === true) {
// Implement data saving operations here.
}
}
navigator オブジェクト内に connection オブジェクトが存在するかどうかを確認することは重要です。これは、Chrome、Chrome for Android、Samsung Internet ブラウザにのみ実装されている Network Information API を表しているためです。そこから、navigator.connection.saveData が true と等しいかどうかを確認するだけで、その条件でデータ保存オペレーションを実装できます。
アプリケーションでサービス ワーカーを使用している場合は、リクエスト ヘッダーを検査し、関連するロジックを適用してエクスペリエンスを最適化できます。また、サーバーは Save-Data リクエスト ヘッダーでアドバタイズされた設定を検索し、別のレスポンス(異なるマークアップ、小さい画像や動画など)を返すこともできます。
実装のヒントとベスト プラクティス
Save-Dataを使用する場合は、それをサポートする UI デバイスを提供し、ユーザーがエクスペリエンスを簡単に切り替えられるようにします。たとえば、次のような情報が得られます。Save-Dataがサポートされていることをユーザーに通知し、使用を促します。- 適切なプロンプトと直感的なオン / オフボタンまたはチェックボックスを使用して、ユーザーがモードを識別して選択できるようにします。
- データ節約モードが選択されている場合は、必要に応じて、データ節約モードを無効にしてフル エクスペリエンスに戻すための簡単でわかりやすい方法を通知して提供します。
- 軽量アプリケーションは、劣ったアプリケーションではないことに注意してください。重要な機能やデータが省略されることはありません。単に、関連する費用とユーザー エクスペリエンスをより意識しているだけです。例:
- フォト ギャラリー アプリでは、低解像度のプレビューを配信したり、コード量の少ないカルーセル メカニズムを使用したりできます。
- 検索アプリケーションは、一度に返す結果の数を減らしたり、メディアを多用する結果の数を制限したり、ページのレンダリングに必要な依存関係の数を減らしたりできます。
- ニュースサイトでは、記事の数を減らしたり、人気のないカテゴリを省略したり、メディア プレビューを小さくしたりできます。
Save-Dataリクエスト ヘッダーを確認するサーバー ロジックを提供し、有効になっている場合は、より軽量な代替ページ レスポンスを提供することを検討します。たとえば、必要なリソースと依存関係の数を減らす、より積極的なリソース圧縮を適用するなどです。Save-Dataヘッダーに基づいて代替レスポンスを配信する場合は、Vary リスト(Vary: Save-Data)に追加して、Save-Dataリクエスト ヘッダーが存在する場合にのみ、このバージョンをキャッシュして配信するようにアップストリーム キャッシュに指示します。詳細については、キャッシュとのやり取りのベスト プラクティスをご覧ください。
- サービス ワーカーを使用している場合、アプリケーションは、
Save-Dataリクエスト ヘッダーの有無を確認するか、navigator.connection.saveDataプロパティの値を確認することで、データ保存オプションが有効になっているかどうかを検出できます。有効になっている場合は、リクエストを書き換えてフェッチするバイト数を減らすか、すでにフェッチされたレスポンスを使用できるかどうかを検討します。 - ユーザーの接続タイプやテクノロジーに関する情報など、他のシグナルで
Save-Dataを補強することを検討してください(NetInfo API を参照)。たとえば、Save-Dataが有効になっていない場合でも、2G 接続のユーザーに軽量なエクスペリエンスを提供したい場合があります。逆に、ユーザーが「高速」な 4G 接続を使用しているからといって、データ節約に関心がないとは限りません。たとえば、ローミング中の場合などです。さらに、Device-MemoryClient Hints を使用してSave-Dataの存在を補強し、メモリが限られているデバイスのユーザーにさらに適応させることもできます。ユーザー デバイスのメモリは、navigator.deviceMemoryクライアント ヒントでもアドバタイズされます。
レシピ
Save-Data で実現できることは、アイデア次第で無限に広がります。どのようなことが可能か、いくつかのユースケースを見てみましょう。このドキュメントを読み進めるうちに、独自のユースケースを思いつくかもしれません。ぜひ、いろいろ試してみてください。
サーバーサイド コードで Save-Data を確認する
Save-Data 状態は、navigator.connection.saveData プロパティを介して JavaScript で検出できますが、サーバー側で検出する方が望ましい場合もあります。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 つは「標準」画面(1x)用の画像、もう 1 つは高解像度画面(Retina ディスプレイなど)用の 2 倍の大きさ(2x)の画像です。このクラスの高解像度画面は、必ずしもハイエンド デバイスに限定されるものではなく、ますます一般的になっています。アプリの動作を軽くしたい場合は、これらの画面に高解像度(2x)の画像ではなく、低解像度(1x)の画像を送信することをおすすめします。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 書き換えモジュールを使用しても同じ結果を得ることができます。比較的少ない構成でこれを実現する方法の例があります。
このコンセプトを CSS の background-image プロパティに拡張するには、<html> 要素にクラスを追加するだけです。
<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 を呼び出すことはないため、Fira Sans が読み込まれることはありません。代わりに Arial が使用されます。Fira Sans ほど見栄えはよくありませんが、データプランを節約したいユーザーには好まれるかもしれません。
概要
Save-Data ヘッダーにはあまりニュアンスがありません。オンかオフのどちらかであり、アプリケーションは、理由に関係なく、その設定に基づいて適切なエクスペリエンスを提供する負担を負います。
たとえば、接続状況が悪い場合でも、アプリのコンテンツや機能が失われる可能性があると疑うユーザーは、データ節約モードを許可しないことがあります。逆に、接続状況が良好な場合でも、ページをできるだけ小さくシンプルに保つために、当然のこととして有効にするユーザーもいます。アプリは、明示的なユーザー操作によって別の指示がない限り、ユーザーが完全で無制限のエクスペリエンスを望んでいると想定するのが最善です。
サイト所有者やウェブ デベロッパーとして、データや費用に制約のあるユーザーのユーザー エクスペリエンスを向上させるために、コンテンツを管理する責任を負いましょう。
Save-Data の詳細と優れた実例については、ユーザーを支援する Save Data をご覧ください。