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

公開日: 2015 年 12 月 8 日

バックグラウンド同期は、ユーザーの接続が安定するまでアクションを保留できるウェブ API です。これにより、ユーザーが送信したいファイルをできるだけ早く送信できるようになります。

Browser Support

  • Chrome: 89.
  • Edge: 89.
  • Firefox: not supported.
  • Safari: not supported.

Source

問題

インターネットは暇つぶしに最適な場所です。インターネットで時間を無駄にしなければ、猫が花を嫌うこと、カメレオンがシャボン玉を好むこと、Eric Bidelman90 年代後半のパットゴルフのヒーローであることは知らなかったでしょう。

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

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

残念ながら、接続状態が悪いと、このエクスペリエンスが頻繁に中断されます。誰もが一度は経験したことがあると思います。白い画面やスピナーを眺めながら、諦めて先に進むべきだとわかっているのに、念のためにもう 10 秒待ってみる。10 秒後にはどうなりますか?特になし。

しかし、なぜ今諦めるのでしょうか?すでに時間を費やしているので、何も得ずに立ち去るのは無駄になるため、待ち続ける。この時点で諦めたくなるかもしれませんが、諦めた瞬間に、待っていればすべてが読み込まれていたことに気づくでしょう。

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

現在、ユーザーがメッセージの [送信] をクリックすると、処理が完了するまでスピナーが表示されます。ユーザーが移動しようとしたり、タブを閉じようとしたりすると、onbeforeunload を使用して「まだこのスピナーを見つめてください」のようなメッセージを表示します。申し訳ございません。」接続がない場合は、「申し訳ございませんが、後日改めてお試しください」と伝えます。

バックグラウンド同期を使用すると、より効率的に作業できます。

ソリューション

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

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

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

バックグラウンド同期は Chrome 49 以降で利用できます。

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

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

プッシュ メッセージと同様に、イベント ターゲットとしてサービス ワーカーを使用するため、ページが開いていない場合でも動作します。まず、ページから同期を登録します。

// 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 がそれらを取得して送信します。

ただし、小さなデータの取得にも使用できます。

オフライン Wikipedia デモ

これは、ページの読み込みを高速化するために作成したオフライン Wikipedia のデモです。その後、バックグラウンド同期の魔法をいくつか追加しました。

実際に試してみましょう。

  1. ブラウザでこのタブを開いたままにしておきます。
  2. 機内モードをオンにするか、Wi-Fi をオフにしてオフラインにします。
  3. 別の記事へのリンクをクリックします。
  4. ページを読み込めなかったことを示すメッセージが表示されます(ページの読み込みに時間がかかっている場合にも表示されます)。
  5. 通知に同意します。
  6. ブラウザを閉じます。
  7. オンライン
  8. 記事がダウンロードされ、キャッシュに保存されて、表示できる状態になると、通知が届きます。

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

権限

私が紹介したデモでは、権限が必要なウェブ通知を使用していますが、バックグラウンド同期自体には権限は必要ありません。

同期イベントは、ユーザーがサイトのページを開いている間に完了することが多いため、ユーザーの権限を要求するとユーザー エクスペリエンスが低下します。代わりに、不正使用を防ぐため、同期を登録してトリガーできるタイミングを制限しています。次に例を示します。

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

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

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

バックグラウンド同期がベースラインになるまで、プログレッシブ エンハンスメントとして使用できます。

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();
}

サービス ワーカーやバックグラウンド同期が利用できない場合は、現在と同じようにページからコンテンツを投稿します。

ユーザーの接続状況が良好に見えても、バックグラウンド同期を使用する価値はあります。バックグラウンド同期は、データの送信中に発生するナビゲーションやタブの閉鎖から保護してくれるからです。

今後について

2016 年前半に Chrome の安定版にバックグラウンド同期をリリースすることを目指しており、同時に「定期的なバックグラウンド同期」というバリエーションの開発も進めています。定期的なバックグラウンド同期では、時間間隔、バッテリーの状態、ネットワークの状態によって制限されたイベントをリクエストできます。もちろん、これにはユーザーの権限が必要であり、これらのイベントがいつ、どのくらいの頻度で発生するかはブラウザ次第です。つまり、ニュースサイトが 1 時間ごとの同期をリクエストしても、ブラウザがユーザーがそのサイトを閲覧するのが午前 7 時だけだと認識していれば、同期は毎日午前 6 時 50 分に実行されます。このアイデアは 1 回限りの同期よりも少し先の話ですが、実現に向けて取り組んでいます。

ウェブの良さを維持しながら、Android と iOS で成功したパターンを少しずつウェブに導入しています。