バックグラウンド同期の導入

バックグラウンド同期は、ユーザーの接続が安定するまでアクションを延期できる新しいウェブ API です。これにより、ユーザーが送信したいものが確実に送信されます。

問題

インターネットは時間を無駄にするのに最適な場所です。インターネットで時間を浪費しなければ、猫は花が嫌いだとか、カメレオンはシャボン玉が大好きだとか、Google の Eric Bidelman90 年代後半のパットゴルフのヒーローだとか、知ることはできません。

時間を無駄にしたくない場合もあるでしょう望ましいユーザー エクスペリエンスは次のようになります。

  1. スマートフォンをポケットから取り出す。
  2. 小さな目標を達成する。
  3. スマートフォンをポケットに戻します。
  4. 生活を再開する。

残念ながら、接続状態が悪いと、このエクスペリエンスが中断されることがあります。誰にもあることです。白い画面またはスピナーを見つめて、あきらめて生活をやめる必要があることはわかっていますが、念のためさらに 10 秒待ちます。10 秒後はどうなりますか?特になし。

でも、ここであきらめるのはもったいない。あなたはすでに時間を費やしているので、何も持たずに立ち去るのは無駄なので、そのまま待ちます。この時点では、あきらめたい気持ちになりますが、あきらめた瞬間に、もう少し待っていればすべて読み込まれていたはずだと後悔することになります。

サービス ワーカーは、キャッシュからコンテンツを配信することで、ページの読み込み部分を解決します。しかし、ページからサーバーに何かを送信する必要がある場合はどうでしょうか。

現時点では、ユーザーがメッセージで [送信] をクリックした場合、メッセージが完了するまでスピナーを見続ける必要があります。タブから移動したり、タブを閉じたりしようとすると、onbeforeunload を使用して、「このスピナーをもう少し見つめてください。申し訳ございません」お客様が接続していない場合は、「申し訳ございませんが、後ほど改めてお試しください」と伝えます。

これはばかげている。バックグラウンド同期を使うとさらに便利に。

ソリューション

次の動画は、絵文字のみのチャットのデモである Emojoy を示しています。これはプログレッシブ ウェブアプリで、オフライン ファーストで動作します。アプリはプッシュ メッセージと通知を使用し、バックグラウンド同期を使用します。

接続がないときにユーザーがメッセージを送信しようとした場合、メッセージは接続が確立されるとバックグラウンドで送信されます。

2016 年 3 月現在、バックグラウンド同期は Chrome バージョン 49 以降でご利用いただけます。動作を確認する手順は次のとおりです。

  1. [Emojoy] を開きます。
  2. オフラインにする(機内モードを使用するか、近くのファラデーケージに移動する)。
  3. メッセージを入力します。
  4. ホーム画面に戻ります(必要に応じてタブまたはブラウザを閉じます)。
  5. インターネットに接続してください。
  6. メッセージがバックグラウンドで送信されます。

このようにバックグラウンドで送信できることも、パフォーマンスの向上を実感しています。アプリはメッセージの送信についてそれほど気にする必要がないため、メッセージをすぐに出力に追加できます。

バックグラウンド同期をリクエストする方法

真の拡張可能なウェブ スタイルで、必要なことを自由に行うことができる低レベルの機能です。ユーザーが接続したときにイベントを発生させるようにリクエストします。ユーザーがすでに接続している場合は、すぐにイベントが発生します。その後、そのイベントをリッスンして必要な処理を行います。

プッシュ メッセージングと同様に、イベント ターゲットとして Service Worker を使用するため、ページが開いていないときにも機能します。同期を開始するには、ページから登録します。

// Register your service worker:
navigator.serviceWorker.register('/sw.js');

// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
  return swRegistration.sync.register('myFirstSync');
});
 ```

Then listen for the event in `/sw.js`:

```js
self.addEventListener('sync', function(event) {
  if (event.tag == 'myFirstSync') {
    event.waitUntil(doSomeStuff());
  }
});

これで完了です。上記の例では、doSomeStuff() は、実行しようとしている処理の成功/失敗を示す Promise を返す必要があります。Promise が満たされると、同期が完了します。失敗した場合は、別の同期が再試行されるようにスケジュールされます。再試行の同期も接続を待機し、指数バックオフを使用します。

同期のタグ名(上記の例では「myFirstSync」)は、特定の同期で一意である必要があります。保留中の同期と同じタグを使用して同期を登録すると、既存の同期と結合されます。つまり、ユーザーがメッセージを送信するたびに「送信トレイ」の同期を登録できますが、オフライン中に 5 件のメッセージを送信した場合、オンラインになったときに同期されるのは 1 回だけです。5 つの個別の同期イベントが必要な場合は、一意のタグを使用します。

最小限の処理を行うシンプルなデモは、同期イベントを使用して通知を表示します。

バックグラウンド同期は何に使用できますか?

理想的には、ページの存続期間を超えて重要なデータの送信をスケジュール設定します。チャット メッセージ、メール、ドキュメントの更新、設定の変更、写真のアップロードなど、ユーザーがタブを移動したり閉じたりしてもサーバーに送信する必要があるもの。ページは、indexedDB の「送信トレイ」ストアにこれらのデータを保存し、Service Worker がデータを取得して送信します。

ただし、少量のデータの取得にも使用できます。

別のデモ

これは、ページ読み込みの高速化のために作成したオフライン ウィキペディアのデモです。その後、バックグラウンド同期の機能を追加しました。

実際に試してみましょう。Chrome 49 以降を使用していることを確認し、以下の手順を行います。

  1. 任意の記事(Chrome など)に移動します。
  2. オフラインにする(機内モードを使用するか、私のようにひどいモバイル プロバイダに加入する)。
  3. 別の記事へのリンクをクリックします。
  4. ページの読み込みに失敗したことが通知されます(ページの読み込みに時間がかかる場合も、このメッセージが表示されます)。
  5. 通知に同意します。
  6. ブラウザを閉じます。
  7. オンライン
  8. 記事がダウンロードされ、キャッシュに保存されて表示可能になると通知が届きます。

このパターンを使用すると、ユーザーはスマートフォンをポケットに入れて日常生活を送ることができます。必要な情報が取得されるとスマートフォンから通知が届きます。

権限

私が示したデモではウェブ通知を使用していますが、これは権限を必要としますが、バックグラウンド同期自体は必要としません。

同期イベントは多くの場合、ユーザーがページを開いている間に完了するため、ユーザーに許可を求めるとエクスペリエンスが低下します。不正行為を防止するため、同期を登録してトリガーできるタイミングを制限しています。例:

  • 同期イベントを登録できるのは、ユーザーがサイトのウィンドウを開いている場合のみです。
  • イベントの実行時間には上限があるため、イベントを使用してサーバーへの ping を x 秒ごとに実行したり、ビットコインをマイニングしたりすることはできません。

もちろん、これらの制限は実際の使用状況に応じて緩んだり緩んだりする可能性があります。

プログレッシブ エンハンスメント

すべてのブラウザでバックグラウンド同期がサポートされるまでには、特に Safari と Edge が Service Worker をまだサポートしていないため、しばらく時間がかかります。ただし、プログレッシブ エンハンスメントは次の点で役立ちます。

if ('serviceWorker' in navigator && 'SyncManager' in window) {
  navigator.serviceWorker.ready.then(function(reg) {
    return reg.sync.register('tag-name');
  }).catch(function() {
    // system was unable to register for a sync,
    // this could be an OS-level restriction
    postDataFromThePage();
  });
} else {
  // serviceworker/sync not supported
  postDataFromThePage();
}

Service Worker やバックグラウンド同期を使用できない場合は、これまでどおりページからコンテンツを投稿します。

バックグラウンド同期は、ユーザーの接続状態は良好に見えても、データ送信中に移動やタブが閉じられることを防ぐので、使用する価値があります。

今後について

バックグラウンド同期は、2016 年前半に Chrome の安定版にリリースされる予定です。また、そのバリエーションである「定期的なバックグラウンド同期」も開発中です。定期的なバックグラウンド同期では、時間間隔、バッテリーの状態、ネットワークの状態によって制限されたイベントをリクエストできます。もちろん、ユーザーの許可が必要になります。また、これらのイベントの発生タイミングと頻度はブラウザによって異なります。つまり、ニュースサイトが 1 時間ごとに同期をリクエストしても、ブラウザがそのサイトを 7 時ちょうどにしか閲覧していないと判断すると、同期は毎日 6 時 50 分に実行されます。このアイデアは、1 回限りの同期とは少し先を行くものですが、間もなく実現する予定です。

Google は、ウェブの優れた点はそのままに、Android や iOS で成功しているパターンをウェブにも少しずつ取り入れています。