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

اندرو گوان
Andrew Guan
دمیان رنزولی
Demián Renzulli

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

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

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

موارد تولید

تیندر

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

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

اسکواش

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

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

استفاده از ورک باکس

به رویدادهای چرخه عمر سرویس ورکر گوش دهید

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

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

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

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

wb.register();

اطلاع‌رسانی به صفحه در مورد تغییرات در داده‌های حافظه پنهان

بسته workbox-broadcast-update در Workbox یک روش استاندارد برای اطلاع‌رسانی به کلاینت‌های پنجره مبنی بر به‌روزرسانی یک پاسخ ذخیره‌شده ارائه می‌دهد. این روش معمولاً همراه با استراتژی 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های مرورگر زیر برای پیاده‌سازی «به‌روزرسانی‌های پخش‌شده» استفاده کنید:

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.
  }
};

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

رابط برنامه‌نویسی کاربردی (API) کلاینت

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

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 ممکن است پیچیده‌تر باشد، زیرا نیاز به مقداردهی اولیه پورت‌ها دارد، اما توسط همه مرورگرهای اصلی پشتیبانی می‌شود.

مراحل بعدی

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

برای الگوهای بیشتر ارتباط Window و Service worker به موارد زیر مراجعه کنید:

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

منابع اضافی