Hizmet çalışanı güncellemelerini anında ele alma

Varsayılan olarak Service Worker'ın yaşam döngüsü, güncellenmiş bir hizmet çalışanı bulunup yüklendiğinde kontrol edilen tüm açık sekmelerin, güncellenmiş hizmet çalışanı etkinleştirilmeden ve kontrolü ele almadan önce kapatılmasını veya bir gezinme sürecinden geçmesini gerektirir.

Çoğu durumda, bunun zaman içinde gerçekleşmesine izin vermek iyi olabilir, ancak bazı durumlarda kullanıcıya beklemede olan bir hizmet çalışanı güncellemesi olduğu konusunda önceden haber vermek ve ardından yeni hizmet çalışanına geçiş sürecini otomatikleştirmek isteyebilirsiniz. Bunu yapmak için sayfanıza ve hizmet çalışanınıza bazı kodlar eklemeniz gerekir.

Sayfanıza yerleştirilecek kod

Aşağıdaki kod, workbox-window sitesinin CDN tarafından barındırılan bir sürümünden içe aktarılan JavaScript modüllerini kullanarak bir satır içi <script> öğesinde çalışır. Bu işlev, workbox-window kullanarak bir hizmet çalışanı kaydeder ve bekleme aşamasında takılırsa tepki verir. Bekleyen bir hizmet çalışanı bulunduğunda bu kod kullanıcıya sitenin güncellenmiş bir sürümünün olduğunu bildirir ve kullanıcıdan yeniden yüklenmesini ister.

<!-- This script tag uses JavaScript modules, so the proper `type` attribute value is required -->
<script type="module">
  // This code sample uses features introduced in Workbox v6.
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');
    let registration;

    const showSkipWaitingPrompt = async (event) => {
      // Assuming the user accepted the update, set up a listener
      // that will reload the page as soon as the previously waiting
      // service worker has taken control.
      wb.addEventListener('controlling', () => {
        // At this point, reloading will ensure that the current
        // tab is loaded under the control of the new service worker.
        // Depending on your web app, you may want to auto-save or
        // persist transient state before triggering the reload.
        window.location.reload();
      });

      // When `event.wasWaitingBeforeRegister` is true, a previously
      // updated service worker is still waiting.
      // You may want to customize the UI prompt accordingly.

      // This code assumes your app has a promptForUpdate() method,
      // which returns true if the user wants to update.
      // Implementing this is app-specific; some examples are:
      // https://open-ui.org/components/alert.research or
      // https://open-ui.org/components/toast.research
      const updateAccepted = await promptForUpdate();

      if (updateAccepted) {
        wb.messageSkipWaiting();
      }
    };

    // Add an event listener to detect when the registered
    // service worker has installed but is waiting to activate.
    wb.addEventListener('waiting', (event) => {
      showSkipWaitingPrompt(event);
    });

    wb.register();
  }
</script>

Kabul ederse messageSkipWaiting() bekleyen hizmet çalışanına self.skipWaiting() çağrısı yapmasını, yani etkinleşmeye başlayacağını bildirir. Etkinleştirildiğinde yeni hizmet çalışanı mevcut istemcilerin kontrolünü ele geçirip workbox-window ürününde controlling etkinliğini tetikler. Böyle bir durumda mevcut sayfa, önceden önbelleğe alınmış tüm öğelerin en son sürümünü ve güncellenmiş hizmet çalışanındaki yeni yönlendirme mantığını kullanarak yeniden yüklenir.

Service Worker'ınıza yerleştirilecek kod

Sayfanızdaki önceki bölümde yer alan kodu aldıktan sonra, hizmet çalışanınıza bekleme aşamasının ne zaman atlanacağını bildiren bir kod eklemeniz gerekir. workbox-build ürününden generateSW kullanıyorsanız ve skipWaiting seçeneği false (varsayılan) olarak ayarlandıysa aşağıdaki kod, oluşturulan hizmet çalışanı dosyanıza otomatik olarak ekleneceği için herhangi bir işlem yapmanız gerekmez.

Kendi hizmet çalışanınızı yazıyorsanız (örneğin, injectManifest modunda Workbox'ın derleme araçlarından biriyle bağlantılı olarak) aşağıdaki kodu kendiniz eklemeniz gerekir:

addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

Bu işlem, workbox-window kaynağından type değeri SKIP_WAITING olan hizmet çalışanına gönderilen mesajları dinler ve böyle bir durumda self.skipWaiting() yöntemini çağırır. Bu iletiyi göndermekten, önceki kod örneğinde gösterilen messageSkipWaiting() workbox-window yöntemindeki yöntem sorumludur.

İstem göstermeniz gerekiyor mu?

Bu, Service Worker dağıtan her uygulamanın uyması gereken bir kalıp değildir. Bu uygulama, Service Worker güncellemesinde bir sayfayı yeniden yükleme fırsatı sunamamanın beklenmeyen davranışlara neden olabileceği belirli senaryolar içindir. Yeniden yükleme istemi göstermeniz gerekip gerekmediğiyle ilgili katı ve hızlı kurallar yoktur, ancak şu durumlar mantıklı olabilir:

  • Önbelleğe almayı kapsamlı olarak kullanıyorsunuz. Statik öğelerle ilgili olarak, gezinme istekleri için ağ öncelikli veya yalnızca ağ stratejisini kullanır, ancak statik öğeleri geç yüklerseniz daha sonra sorunlar yaşayabilirsiniz. Bu durum, sürümüne sahip öğelerin değişebileceği ve bir hizmet çalışanının bunları önceden önbelleğe almadığı durumlara neden olabilir. Burada yeniden yükle düğmesi sunmak, bazı beklenmedik davranışları önleyebilir.
  • Önceden önbelleğe alınmış HTML sunuyorsanız. Bu durumda, hizmet çalışanı güncellemelerinde bir yeniden yükleme düğmesi sunmayı kesinlikle düşünmelisiniz. Çünkü bu HTML'de yapılan güncellemeler, güncellenen hizmet çalışanı kontrolü ele geçirene kadar tanınmayacaktır.
  • Çoğunlukla çalışma zamanı önbelleğe alma yöntemini kullanmıyorsanız. Kaynakları çalışma zamanında önbelleğe alırken, kullanıcıya yeniden yüklenmesi gerektiğini bildirmeniz gerekmez. Sürümlü öğeler değiştikçe, gezinme isteklerinde ağ öncelikli veya yalnızca ağ stratejisi kullanıldığı varsayılarak bu öğeler çalışma zamanı önbelleğine eklenir.
  • stale-when-reValidate stratejisi kullanırken kullanıcıları Service Worker güncellemeleri hakkında bilgilendirmek için workbox-broadcast-update modülünü kullanabilirsiniz.

Service Worker'da yapılan güncellemeleri kullanıcıya bildirmeniz gerekip gerekmediği uygulamanıza ve benzersiz gereksinimlerine bağlıdır. Yeni bir hizmet çalışanı devreye soktuğunuzda kullanıcılarınızın garip davranışlarla karşılaştığını fark ederseniz bu, muhtemelen onları bilgilendirmeniz gereken en iyi sinyaldir.