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

Varsayılan olarak hizmet çalışanı yaşam döngüsü, güncellenmiş bir hizmet çalışanı bulunduğunda ve yüklendiğinde, güncellenen hizmet çalışanı etkinleştirilip kontrolü ele almadan önce mevcut hizmet çalışanının kontrol ettiği tüm açık sekmelerin kapatılmasını veya gezinmeden geçilmesini gerektirir.

Çoğu durumda, bu işleme zaman içinde izin vermek iyi olabilir ancak bazı durumlarda, beklemede olan bir Service Worker güncellemesi olduğu konusunda kullanıcıya bilgi vermek ve 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 koyacağınız kod

Aşağıdaki kod, workbox-window ürününün CDN tarafından barındırılan bir sürümünden içe aktarılan JavaScript modüllerini kullanarak satır içi bir <script> öğesinde çalışır. Bu hizmet, workbox-window kullanarak bir hizmet çalışanı kaydeder ve hizmet çalışanı 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üklemesini 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>

İstek kabul edilirse messageSkipWaiting(), bekleyen hizmet çalışanına self.skipWaiting() komutunu çağırmasını söyler. Böylece hizmet etkinleştirilmeye başlar. Etkinleştirme işleminin ardından yeni hizmet çalışanı mevcut istemcilerin kontrolünü ele alarak workbox-window içinde controlling etkinliğini tetikler. Bu durumda mevcut sayfa, önbelleğe alınmış tüm öğelerin en son sürümünü ve güncellenen hizmet çalışanında bulunan yeni yönlendirme mantığını kullanarak yeniden yüklenir.

Hizmet çalışanınıza yerleştireceğiniz kod

Sayfanızın bir önceki bölümünde bulunan 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 adlı sağlayıcıdan generateSW kullanıyorsanız ve skipWaiting seçeneği false (varsayılan) olarak ayarlandıysa aşağıdaki kod, oluşturulan Service Worker dosyanıza otomatik olarak eklenir.

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

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

Bu işlem, hizmet çalışanına workbox-window tarafından type değeri SKIP_WAITING olan, gönderilen mesajları dinler ve bu durumda self.skipWaiting() komutunu çağırır. Bu mesajın gönderilmesinden, önceki kod örneğinde gösterilen workbox-window uygulamasında gösterilen messageSkipWaiting() yöntemi sorumludur.

İstem göstermeniz gerekiyor mu?

Bu, Service Worker dağıtan her uygulamanın uyması gereken bir kalıp değildir. Service Worker güncellemesinde bir sayfayı yeniden yükleme fırsatı sağlayamamanız beklenmedik davranışlara yol açabilir. Yeniden yükleme istemi gösterip göstermemeniz gerektiğine ilişkin kesin ve hızlı bir kural yoktur, ancak mantıklı olabilecek birkaç durum aşağıda verilmiştir:

  • Önbelleğe almayı yoğun bir şekilde kullanıyorsunuz. Statik öğeler söz konusu olduğunda, gezinme istekleri için ağ öncelikli veya yalnızca ağ stratejisini kullanır ve statik öğeleri geç yüklerseniz daha sonra sorun yaşayabilirsiniz. Bu durum, sürümü oluşturulmuş öğelerin değişebileceği ve bir hizmet çalışanının bunları önceden önbelleğe almamış olabileceği durumlara neden olabilir. Burada yeniden yükleme düğmesi sunmak, bazı beklenmedik davranışların önüne geçebilir.
  • Ön belleğe alınmış HTML sunuyorsanız. Bu durumda, güncellenen hizmet çalışanı kontrolü ele alana kadar bu HTML'de yapılan güncellemeler tanınmayacağı için Service Worker güncellemelerinde yeniden yükleme düğmesi sunmayı önemle değerlendirmeniz gerekir.
  • Çalışma zamanı önbelleğe alma işlemlerinde çoğunlukla yararlanmıyorsanız. Kaynakları çalışma zamanında önbelleğe alırken kullanıcıya yeniden yüklemeleri gerektiğini bildirmeniz gerekmez. Sürümlü öğeler değiştikçe, gezinme isteklerinin ağ öncelikli veya yalnızca ağ stratejisini kullandığı varsayılarak bu öğeler zaman içinde çalışma zamanı önbelleğine eklenir.
  • stale-when-reverification stratejisi kullanırken kullanıcıları Service Worker güncellemeleri hakkında bilgilendirmek için workbox-broadcast-update modülünü kullanabilirsiniz.

Service Worker güncellemeleri konusunda kullanıcıyı bilgilendirmenizin gerekip gerekmediği, uygulamanıza ve uygulamanın benzersiz gereksinimlerine bağlıdır. Yeni bir Service Worker'ı aktarırken kullanıcılarınızın tuhaf davranışlar sergilediğini fark ederseniz onları bilgilendirmeniz gereken en iyi sinyal muhtemelen budur.