به‌روزرسانی‌ها را در صفحاتی با کارکنان خدمات پخش کنید

اندرو گوان
Andrew Guan

در برخی از سناریوها، سرویس‌کار ممکن است نیاز داشته باشد که به طور فعال با هر یک از برگه‌های فعالی که کنترل می‌کند ارتباط برقرار کند تا از یک رویداد خاص مطلع شود. مثالها عبارتند از:

  • هنگامی که نسخه جدیدی از سرویس‌کار نصب شده است، به صفحه اطلاع می‌دهد تا صفحه دکمه «به‌روزرسانی برای تازه‌سازی» را به کاربر نشان دهد تا فوراً به عملکرد جدید دسترسی پیدا کند.
  • با نشان دادن علامتی مانند: "برنامه اکنون برای کار آفلاین آماده است" یا "نسخه جدید محتوای موجود" ، به کاربر اطلاع دهید که تغییری در داده‌های حافظه پنهان که در سمت کارمند سرویس رخ داده است.
نموداری که یک کارگر خدماتی را در حال ارتباط با صفحه برای ارسال به‌روزرسانی نشان می‌دهد.

ما این نوع موارد استفاده را که در آن سرویس‌دهنده نیازی به دریافت پیامی از صفحه برای شروع ارتباط ندارد ، «به‌روزرسانی‌های پخش» می‌نامیم. در این راهنما روش‌های مختلف پیاده‌سازی این نوع ارتباط بین صفحات و کارکنان خدمات را با استفاده از APIهای استاندارد مرورگر و کتابخانه Workbox مرور می‌کنیم.

موارد تولید Tinder

Tinder PWA workbox-window برای گوش دادن به لحظات مهم چرخه عمر کارگر خدمات از صفحه ("نصب شده"، "کنترل شده" و "فعال شده") استفاده می کند. به این ترتیب وقتی یک سرویس‌کار جدید وارد بازی می‌شود، یک بنر «به‌روزرسانی موجود» را نشان می‌دهد تا بتواند PWA را تازه‌سازی کرده و به آخرین ویژگی‌ها دسترسی داشته باشد:

تصویری از قابلیت «به‌روزرسانی موجود» برنامه وب Tinder.
در Tinder PWA، سرویس‌کار به صفحه می‌گوید که نسخه جدید آماده است و صفحه بنر «به‌روزرسانی موجود» را به کاربران نشان می‌دهد.
اسکووش

در Squoosh PWA ، هنگامی که سرویس‌کار تمام دارایی‌های لازم برای کار آفلاین را در حافظه پنهان ذخیره می‌کند، پیامی به صفحه ارسال می‌کند تا نان تست "آماده برای کار آفلاین" را نشان دهد و کاربر را از ویژگی مطلع می‌کند:

تصویری از عملکرد برنامه وب Squoosh "آماده برای کار آفلاین".
در Squoosh PWA، سرویس‌کار هنگامی که کش آماده شد، به‌روزرسانی را برای صفحه پخش می‌کند، و صفحه نان تست «آماده برای کار آفلاین» را نمایش می‌دهد.
با استفاده از Workbox به رویدادهای چرخه عمر کارگر خدمات گوش دهید

workbox-window یک رابط ساده برای گوش دادن به رویدادهای مهم چرخه عمر کارگر خدمات ارائه می دهد. این کتابخانه از APIهای سمت کلاینت مانند updatefound و statechange استفاده می‌کند و شنوندگان رویدادهای سطح بالاتری را در شی workbox-window ارائه می‌کند، که مصرف این رویدادها را برای کاربر آسان‌تر می‌کند.

کد صفحه زیر به شما امکان می دهد هر بار که نسخه جدیدی از Service Worker نصب می شود شناسایی کنید، بنابراین می توانید آن را به کاربر اطلاع دهید:

const wb = new Workbox('/sw.js');

wb.addEventListener('installed', (event) => {
  if (event.isUpdate) {
    // Show "Update App" banner
  }
});

wb.register();
صفحه را از تغییرات داده های کش مطلع کنید

بسته Workbox workbox-broadcast-update یک روش استاندارد برای اطلاع رسانی به مشتریان پنجره در مورد به روز رسانی پاسخ ذخیره شده در حافظه پنهان ارائه می دهد. این معمولاً همراه با استراتژی StaleWhileRevalidate استفاده می شود.

برای پخش به‌روزرسانی‌ها، یک broadcastUpdate.BroadcastUpdatePlugin به گزینه‌های استراتژی خود در سمت کارگر اضافه کنید:

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {BroadcastUpdatePlugin} from 'workbox-broadcast-update';

registerRoute(
  ({url}) => url.pathname.startsWith('/api/'),
  new StaleWhileRevalidate({
    plugins: [
      new BroadcastUpdatePlugin(),
    ],
  })
);

در برنامه وب خود، می توانید به این رویدادها گوش دهید:

navigator.serviceWorker.addEventListener('message', async (event) => {
  // Optional: ensure the message came from workbox-broadcast-update
  if (event.data.meta === 'workbox-broadcast-update') {
    const {cacheName, updatedUrl} = event.data.payload;

    // Do something with cacheName and updatedUrl.
    // For example, get the cached content and update
    // the content on the page.
    const cache = await caches.open(cacheName);
    const updatedResponse = await cache.match(updatedUrl);
    const updatedText = await updatedResponse.text();
  }
});
استفاده از API های مرورگر

اگر عملکردی که Workbox ارائه می‌کند برای نیازهای شما کافی نیست، از APIهای مرورگر زیر برای اجرای «به‌روزرسانی‌های پخش» استفاده کنید:

Broadcast Channel API

سرویس دهنده یک شی BroadcastChannel ایجاد می کند و شروع به ارسال پیام به آن می کند. هر زمینه (به عنوان مثال صفحه) علاقه مند به دریافت این پیام ها می تواند یک شی BroadcastChannel را نمونه سازی کند و یک کنترل کننده پیام را برای دریافت پیام ها پیاده سازی کند.

برای اطلاع رسانی به صفحه هنگام نصب سرویس کار جدید، از کد زیر استفاده کنید:

// Create Broadcast Channel to send messages to the page
const broadcast = new BroadcastChannel('sw-update-channel');

self.addEventListener('install', function (event) {
  // Inform the page every time a new service worker is installed
  broadcast.postMessage({type: 'CRITICAL_SW_UPDATE'});
});

این صفحه با عضویت در sw-update-channel به این رویدادها گوش می دهد:

// Create Broadcast Channel and listen to messages sent to it
const broadcast = new BroadcastChannel('sw-update-channel');

broadcast.onmessage = (event) => {
  if (event.data && event.data.type === 'CRITICAL_SW_UPDATE') {
    // Show "update to refresh" banner to the user.
  }
};

این یک تکنیک ساده است، اما محدودیت آن پشتیبانی از مرورگر است: در لحظه نوشتن این مقاله، Safari از این API پشتیبانی نمی‌کند .

Client API

Client API با تکرار روی آرایه ای از اشیاء Client راه ساده ای برای برقراری ارتباط با چندین مشتری از سرویس کارمند ارائه می دهد.

از کد سرویس کارگر زیر برای ارسال پیام به آخرین برگه متمرکز استفاده کنید:

// Obtain an array of Window client objects
self.clients.matchAll(options).then(function (clients) {
  if (clients && clients.length) {
    // Respond to last focused tab
    clients[0].postMessage({type: 'MSG_ID'});
  }
});

این صفحه یک کنترل کننده پیام را برای رهگیری این پیام ها پیاده سازی می کند:

// Listen to messages
navigator.serviceWorker.onmessage = (event) => {
     if (event.data && event.data.type === 'MSG_ID') {
         // Process response
   }
};

Client API یک گزینه عالی برای مواردی مانند پخش اطلاعات به چندین تب فعال است. API توسط همه مرورگرهای اصلی پشتیبانی می شود، اما همه روش های آن پشتیبانی نمی شوند. قبل از استفاده از آن، پشتیبانی مرورگر را بررسی کنید.

کانال پیام

کانال پیام به یک مرحله پیکربندی اولیه نیاز دارد، با ارسال یک پورت از صفحه به سرویس دهنده، تا یک کانال ارتباطی بین آنها ایجاد شود. صفحه یک شی MessageChannel را نمونه‌سازی می‌کند و یک پورت را از طریق رابط postMessage() به سرویس‌کار ارسال می‌کند:

const messageChannel = new MessageChannel();

// Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
  messageChannel.port2,
]);

صفحه با پیاده سازی یک کنترل کننده "onmessage" در آن پورت به پیام ها گوش می دهد:

// Listen to messages
messageChannel.port1.onmessage = (event) => {
  // Process message
};

سرویس‌کار پورت را دریافت می‌کند و مرجعی را به آن ذخیره می‌کند:

// Initialize
let communicationPort;

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'PORT_INITIALIZATION') {
    communicationPort = event.ports[0];
  }
});

از آن نقطه می تواند با فراخوانی postMessage() در مرجع پورت، پیام هایی را به صفحه ارسال کند:

// Communicate
communicationPort.postMessage({type: 'MSG_ID' });

به دلیل نیاز به مقداردهی اولیه پورت ها، ممکن است MessageChannel برای پیاده سازی پیچیده تر باشد، اما توسط همه مرورگرهای اصلی پشتیبانی می شود.

مراحل بعدی

در این راهنما، ما یک مورد خاص از ارتباطات کارگر سرویس پنجره را بررسی کردیم: "به روز رسانی پخش" . نمونه‌های بررسی‌شده شامل گوش دادن به رویدادهای مهم چرخه عمر کارکنان خدمات، و برقراری ارتباط با صفحه در مورد تغییرات در محتوا یا داده‌های ذخیره‌شده است. می توانید موارد استفاده جالب تری را در نظر بگیرید که در آن سرویس دهنده به طور فعال با صفحه ارتباط برقرار می کند، بدون اینکه قبلاً هیچ پیامی دریافت کند.

برای الگوهای بیشتر ارتباطات پنجره و سرویس کار، بررسی کنید:

  • راهنمای ذخیره سازی ضروری : فراخوانی یک سرویس دهنده از صفحه برای ذخیره منابع از قبل (به عنوان مثال در سناریوهای واکشی اولیه).
  • ارتباط دو طرفه : تفویض یک کار به یک کارگر خدماتی (مثلاً یک بارگیری سنگین)، و اطلاع رسانی صفحه از پیشرفت.
منابع اضافی