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
オブジェクトが存在するかどうかを確認することが重要です。これは 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
状態は 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 つは「標準」画面用(1 倍)で、もう 1 つは高解像度画面用(2 倍)の画像です(例: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 書き換えモジュールを使用して同じ結果を得ることもできます。比較的少ない構成でこれを実現する方法の例があります。
このコンセプトを 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
をご覧ください。