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

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

問題

インターネットは時間を浪費するのに最適な場所です。インターネットに無駄な時間を費やさなければ、猫は花が嫌いカメレオンはバブルが好きなこと、エリック ビデルマン90 年代後半のパットパットゴルフのヒーローであることは知りません。

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

  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 で成功しているパターンをウェブにも少しずつ取り入れています。