• 2015/12/13 : update() とブラウザキャッシュのインタラクションについて仕様変更があったので追記しました。Chrome 48 から適用されます。
  • 2015/12/13 : update() が Promise を返すように仕様変更があったので追記しました。Chrome 46 から適用されます。

Chrome に ServiceWorkerRegistration.update() を実装したのでその紹介。Chrome 45 から使用することができます。

Service Worker は適当なタイミングでスクリプトのアップデートチェックが走ります。例えば Service Worker のコントロール下にあるページを開いたときにチェックします (Handle Fetch Algorithm 参照)。このアップデートチェックはスクリプトの Cache-Control ヘッダに従うため、もし頻繁にスクリプトを更新しないのであれば max-age を指定してあげることで不要なチェックを省くことができます。

一方で、もし何らかの理由で max-age に長大な時間が設定された場合は、スクリプトがなかなか更新されないことになります。このようなスクリプトの焼付けを防ぐために、Service Worker では最後の更新から 24 時間以上が経った場合はキャッシュの有無に関わらず必ずアップデートチェックを実行します (Update Algorithm 参照)。

update() はこの「キャッシュを無視するアップデートチェック」をスクリプトから行えるようにしたものです (2015/12/13 追記: Chrome 48 から update() もスクリプトの Cache-Control ヘッダに従うようになりました。前回更新から 24 時間以上経った場合は今まで通りキャッシュを無視してチェックを行います (Dashboard))。

例えば次のように使います (2015/12/13 追記: Chrome 46 から update() が Promise を返すようになりました (Dashboard))。

navigator.serviceWorker.getRegistration()
  .then(function(registration) { return registration.update(); })
  .then(function() {
      // The script is updated, or there is no updated script.
    })
  .catch(function(e) {
      // An error occurs during update (eg. Network error, Runtime error).
    });

更新があった場合は updatefound イベントが発火します。

registration.addEventListener('updatefound', function() {
  // A new worker is coming!
  console.assert(registration.installing);
});

Service Worker の実行コンテキスト上でも使えます。

// sw.js
self.registration.update();

ちなみに update() を呼んだからといってすぐに コントローラー である Service Worker が入れ替わるわけではありません。現在のコントローラーによってコントロールされているページが全て閉じられてから入れ替わります (Service Worker ハッカソンのスライド 参照)。コントロールされているページがあったとしても強制的にコントローラーを入れ替える skipWaiting() という API もあります。