データの保存で高速かつ軽量なアプリケーションを提供

Chrome、Opera、Yandex ブラウザで利用できる Save-Data クライアント ヒント リクエスト ヘッダーを使用すると、ブラウザでデータ保存モードを有効にしているユーザーに、より軽量で高速なアプリケーションを提供できます。

軽量なページの必要性

Weblight の統計情報

ウェブページの速度が速く、軽量であるほど、ユーザー エクスペリエンスが向上し、コンテンツの理解度と記憶度が高まり、コンバージョンと収益が増加することは、誰もが認めるところです。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 を表しており、Chrome、Chrome for Android、Samsung Internet ブラウザでのみ実装されているためです。そこから、navigator.connection.saveDatatrue と等しいかどうかを確認するだけで、その条件でデータ保存オペレーションを実装できます。

Chrome のデベロッパー ツールで表示された Save-Data ヘッダーとデータ セーバー拡張機能。
パソコン版 Chrome でデータセーバー拡張機能を有効にする。

アプリケーションでサービス ワーカーを使用している場合、リクエスト ヘッダーを検査し、関連するロジックを適用してエクスペリエンスを最適化できます。または、サーバーは Save-Data リクエスト ヘッダーでアドバタイズされた設定を探し、代替レスポンス(異なるマークアップ、小さい画像や動画など)を返すこともできます。

実装のヒントとベスト プラクティス

  1. Save-Data を使用する場合は、それをサポートする UI デバイスを提供し、ユーザーがエクスペリエンスを簡単に切り替えられるようにします。たとえば、次のような情報が得られます。
    • Save-Data がサポートされていることをユーザーに通知し、使用を促します。
    • 適切なプロンプトと直感的なオン/オフ ボタンまたはチェックボックスを使用して、ユーザーがモードを識別して選択できるようにします。
    • データ保存モードが選択されている場合は、その旨を通知し、必要に応じて無効にして完全なエクスペリエンスに戻すための簡単でわかりやすい方法を提供します。
  2. 軽量アプリケーションは劣ったアプリケーションではありません。重要な機能やデータを省略するのではなく、関連する費用とユーザー エクスペリエンスをより意識しているだけです。例:
    • フォト ギャラリー アプリケーションは、低解像度のプレビューを配信したり、コードの少ないカルーセル メカニズムを使用したりする場合があります。
    • 検索アプリケーションでは、一度に返される結果の数を減らしたり、メディアを多用した結果の数を制限したり、ページをレンダリングするために必要な依存関係の数を減らしたりすることがあります。
    • ニュース中心のサイトでは、表示する記事数を減らしたり、人気のないカテゴリを省略したり、メディアのプレビューを小さくしたりすることがあります。
  3. Save-Data リクエスト ヘッダーを確認するサーバー ロジックを提供し、有効になっている場合は代替の軽量なページ レスポンスを提供することを検討します(必要なリソースと依存関係の数を減らす、より積極的なリソース圧縮を適用するなど)。
    • Save-Data ヘッダーに基づいて代替レスポンスを配信する場合は、Vary リスト(Vary: Save-Data)に追加して、Save-Data リクエスト ヘッダーが存在する場合にのみこのバージョンをキャッシュに保存して配信するようアップストリーム キャッシュに指示してください。詳しくは、キャッシュとのやり取りに関するベスト プラクティスをご覧ください。
  4. Service Worker を使用している場合、アプリケーションは Save-Data リクエスト ヘッダーの有無を確認するか、navigator.connection.saveData プロパティの値を確認することで、データ保存オプションが有効になっているかどうかを検出できます。有効になっている場合は、リクエストを書き換えて取得するバイト数を減らすか、すでに取得済みのレスポンスを使用できるかどうかを検討します。
  5. ユーザーの接続タイプやテクノロジーに関する情報など、他のシグナルで 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 では、リクエスト ヘッダーは 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 倍)用、もう 1 つは高解像度画面(Retina ディスプレイなど)用の 2 倍の大きさの画像です。このクラスの高解像度画面は、必ずしもハイエンド デバイスに限定されるものではなく、ますます一般的になっています。軽量なアプリ エクスペリエンスが望ましい場合は、大きな(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 がない場合に読み込まれる重要でない画像と、Save-Data がある場合に省略される同じ画像の比較。
データ セーバーがない場合に読み込まれる重要でない画像と、データ セーバーがある場合に省略される同じ画像の比較。

もちろん、画像を省略するだけではありません。Save-Data を使用して、特定の書体など、重要でない他のリソースの送信を省略することもできます。

不要なウェブフォントを省略する

ウェブフォントは通常、画像ほどページ全体のペイロードを占めることはありませんが、それでも非常に人気があります。また、消費するデータ量も無視できるほどではありません。さらに、ブラウザがフォントを取得してレンダリングする方法は、想像以上に複雑です。FOITFOUT、ブラウザのヒューリスティックなどの概念により、レンダリングは微妙な操作になります。

そのため、ユーザー エクスペリエンスを簡素化したいユーザーのために、重要でないウェブフォントを省略したいと考えるのは当然かもしれません。Save-Data を使用すると、この作業を比較的簡単に行うことができます。

たとえば、サイトに Google FontsFira 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;
}

このアプローチでは、ブラウザが CSS リソース(ウェブフォントを含む)を投機的に読み込むため、Google Fonts の <link> スニペットをそのまま残すことができます。ブラウザは、まず DOM にスタイルを適用し、次に HTML 要素がスタイルシート内のリソースを呼び出しているかどうかを確認します。Save-Data がオンになっている状態でユーザーがアクセスした場合、スタイル設定された DOM が Fira Sans を呼び出すことはないため、Fira Sans は読み込まれません。代わりに Arial が使用されます。Fira Sans ほどではありませんが、データプランを節約したいユーザーには適しているかもしれません。

概要

Save-Data ヘッダーにはニュアンスはあまりありません。オンかオフのどちらかであり、理由に関係なく、アプリは設定に基づいて適切なエクスペリエンスを提供する責任を負います。

たとえば、接続状況が悪い場合でも、アプリのコンテンツや機能が失われる可能性があると疑われる場合は、データ保存モードを許可しないユーザーもいます。逆に、接続状況が良好な場合でも、ページをできるだけ小さくシンプルに保つために、この機能を常に有効にしているユーザーもいます。明示的なユーザー アクションによって明確な指示がない限り、アプリはユーザーが完全な無制限のエクスペリエンスを望んでいると想定するのが最適です。

サイト所有者とウェブ デベロッパーは、データと費用に制約のあるユーザーのユーザー エクスペリエンスを向上させるために、コンテンツを管理する責任を負う必要があります。

Save-Data の詳細と優れた実践例については、ユーザーの Save Data を支援するをご覧ください。