Chrome、Opera、Yandex の各ブラウザで利用可能な Save-Data
クライアント ヒント リクエスト ヘッダーにより、デベロッパーは、ブラウザでデータ節約モードを有効にしているユーザーに、より軽量で高速なアプリケーションを提供できます。
軽量ページの必要性
高速で軽量なウェブページは、ユーザー エクスペリエンスの向上、コンテンツの理解と保持の向上、コンバージョンと収益の増加につながることは、誰もが認めるところです。Google の調査によると、「最適化したページの読み込みは元のページより 4 倍速く、使用するバイト数も 80% 削減されます。また、こうしたページは高速で読み込めるため、ページヘのトラフィックも 50% 増加しました。」
2G 接続の数はようやく減少に転じていますが、2015 年には依然として主流のネットワーク テクノロジーでした。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
リクエスト ヘッダーを追加します。現時点では、ブラウザはヘッダーに 1 つの *on トークン(Save-Data: 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-Memory
クライアント ヒントを使用してSave-Data
の存在を補強し、メモリが限られているデバイスのユーザーにさらに適応させることができます。ユーザーのデバイスのメモリは、navigator.deviceMemory
クライアント ヒントでもアドバタイズされます。
レシピ
Save-Data
で実現できることは、考えうるものに限られます。どのようなことができるか、いくつかのユースケースを見てみましょう。この記事を読んでいるうちに、他のユースケースが思い浮かぶかもしれません。ぜひ試して、可能性を探ってみましょう。
サーバーサイド コードで Save-Data
を確認する
Save-Data
状態は navigator.connection.saveData
プロパティを使用して JavaScript で検出できますが、サーバーサイドで検出することをおすすめします。場合によっては、JavaScript が実行できないことがあります。また、サーバーサイド検出は、マークアップをクライアントに送信する前に変更する唯一の方法です。これは、Save-Data
の最も有益なユースケースの一部に関連しています。
サーバーサイド コードで Save-Data
ヘッダーを検出するための具体的な構文は、使用する言語によって異なりますが、基本的な考え方はどのアプリケーション バックエンドでも同じです。たとえば、PHP では、リクエスト ヘッダーは $_SERVER
スーパーグローバル配列の HTTP_
で始まるインデックスに保存されます。つまり、次のように $_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 つは高解像度画面用に 2 倍の大きさ(2x)の画像です(例: Retina ディスプレイ)。このクラスの高解像度画面は、ハイエンド デバイスに限定されるわけではなく、ますます一般的になっています。軽量なアプリケーション エクスペリエンスが望まれる場合は、大画面(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
ヘッダーが存在する場合に <html>
要素に save-data
クラスを追加すると、最初は必須ではない書体を使用して、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
をご覧ください。