ایجاد تجارب جستجوی انعطاف‌پذیر با Workbox

این کد لبه به شما نشان می دهد که چگونه یک تجربه جستجوی انعطاف پذیر را با Workbox پیاده سازی کنید. برنامه نمایشی که استفاده می‌کند شامل یک کادر جستجو است که یک نقطه پایانی سرور را فراخوانی می‌کند و کاربر را به یک صفحه HTML اصلی هدایت می‌کند.

اندازه گیری کنید

قبل از افزودن بهینه سازی، همیشه ایده خوبی است که ابتدا وضعیت فعلی برنامه را تجزیه و تحلیل کنید.

  • روی Remix to Edit کلیک کنید تا پروژه قابل ویرایش باشد.
  • برای پیش نمایش سایت، View App را فشار دهید. سپس تمام صفحه را فشار دهید تمام صفحه .

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

  1. «Control+Shift+J» (یا «Command+Option+J» در Mac) را فشار دهید تا DevTools باز شود.
  2. روی تب Network کلیک کنید.
  3. Chrome DevTools را باز کنید و پنل Network را انتخاب کنید.
  4. در لیست کشویی Throttling ، Offline را انتخاب کنید.
  5. در برنامه آزمایشی یک عبارت جستجو را وارد کنید، سپس روی دکمه جستجو کلیک کنید.

صفحه خطای استاندارد مرورگر نشان داده شده است:

تصویری از UX پیش فرض آفلاین در مرورگر.

یک پاسخ بازگشتی ارائه دهید

Service Worker حاوی کدی است که صفحه آفلاین را به لیست پیش کش اضافه می کند، بنابراین همیشه می توان آن را در رویداد install سرویس دهنده ذخیره کرد.

معمولاً باید به Workbox دستور دهید تا این فایل را در زمان ساخت، با ادغام کتابخانه با ابزار ساخت انتخابی خود (به عنوان مثال webpack یا gulp ) به لیست پیش کش اضافه کند.

برای سادگی، ما قبلاً آن را برای شما انجام داده ایم. کد زیر در public/sw.js این کار را انجام می دهد:

const FALLBACK_HTML_URL = '/index_offline.html';

workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

سپس، کدی را برای استفاده از صفحه آفلاین به عنوان پاسخ بازگشتی اضافه کنید:

  1. برای مشاهده منبع، View Source را فشار دهید.
  2. کد زیر را به پایین public/sw.js اضافه کنید:
workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());

workbox.routing.setCatchHandler(({event}) => {
  switch (event.request.destination) {
    case 'document':
      return caches.match(FALLBACK_HTML_URL);
      break;
    default:
      return Response.error();
  }
});

کد زیر را انجام می دهد:

  • یک استراتژی پیش‌فرض Network Only را تعریف می‌کند که برای همه درخواست‌ها اعمال می‌شود.
  • با فراخوانی workbox.routing.setCatchHandler() برای مدیریت درخواست های ناموفق، یک کنترل کننده خطای جهانی را اعلام می کند. هنگامی که درخواست ها برای اسناد هستند، یک صفحه HTML آفلاین بازگشتی برگردانده می شود.

برای تست این عملکرد:

  1. به برگه دیگری که برنامه شما را اجرا می کند، برگردید.
  2. لیست کشویی Throttling را به حالت آنلاین برگردانید.
  3. دکمه بازگشت Chrome را فشار دهید تا به صفحه جستجو برگردید.
  4. مطمئن شوید که چک باکس Disable cache در DevTools غیرفعال است.
  5. دکمه بارگیری مجدد Chrome را به مدت طولانی فشار دهید و برای اطمینان از به‌روزرسانی سرویس‌کارتان ، خالی کردن حافظه پنهان و بارگذاری مجدد سخت را انتخاب کنید.
  6. لیست کشویی Throttling را دوباره به حالت آفلاین برگردانید.
  7. یک عبارت جستجو را وارد کنید و دوباره روی دکمه جستجو کلیک کنید.

صفحه HTML بازگشتی نشان داده شده است:

تصویری از UX آفلاین سفارشی در مرورگر.

درخواست مجوز اعلان

برای سادگی، صفحه آفلاین در views/index_offline.html قبلاً حاوی کد درخواست مجوزهای اعلان در یک بلوک اسکریپت در پایین است:

function requestNotificationPermission(event) {
  event.preventDefault();

  Notification.requestPermission().then(function (result) {
    showOfflineText(result);
  });
}

کد زیر را انجام می دهد:

  • وقتی کاربر روی اشتراک در اعلان‌ها کلیک می‌کند، تابع requestNotificationPermission() فراخوانی می‌شود که Notification.requestPermission() را فراخوانی می‌کند تا درخواست مجوز پیش‌فرض مرورگر را نشان دهد. این قول با مجوز انتخاب شده توسط کاربر حل می شود، که می تواند granted ، denied یا default باشد.
  • مجوز حل شده را به showOfflineText() می دهد تا متن مناسب را به کاربر نشان دهد.

پرس و جوهای آفلاین را ادامه دهید و وقتی آنلاین شدید دوباره امتحان کنید

در مرحله بعد، Workbox Background Sync را برای تداوم پرس و جوهای آفلاین پیاده سازی کنید تا زمانی که مرورگر تشخیص داد که اتصال بازگشته است، آنها را دوباره امتحان کنید.

  1. public/sw.js را برای ویرایش باز کنید.
  2. کد زیر را در انتهای فایل اضافه کنید:
const bgSyncPlugin = new workbox.backgroundSync.Plugin('offlineQueryQueue', {
  maxRetentionTime: 60,
  onSync: async ({queue}) => {
    let entry;
    while ((entry = await queue.shiftRequest())) {
      try {
        const response = await fetch(entry.request);
        const cache = await caches.open('offline-search-responses');
        const offlineUrl = `${entry.request.url}&notification=true`;
        cache.put(offlineUrl, response);
        showNotification(offlineUrl);
      } catch (error) {
        await this.unshiftRequest(entry);
        throw error;
      }
    }
  },
});

کد زیر را انجام می دهد:

  • workbox.backgroundSync.Plugin حاوی منطقی است که درخواست‌های ناموفق را به یک صف اضافه می‌کند تا بعداً دوباره امتحان شوند. این درخواست ها در IndexedDB ادامه خواهند داشت.
  • maxRetentionTime مقدار زمانی را که ممکن است یک درخواست دوباره امتحان شود را نشان می دهد. در این مورد ما 60 دقیقه را انتخاب کرده ایم (پس از آن دور ریخته می شود).
  • onSync مهمترین بخش این کد است. هنگامی که اتصال دوباره برقرار می شود، این تماس برگشتی فراخوانی می شود تا درخواست های در صف بازیابی و سپس از شبکه واکشی شوند.
  • پاسخ شبکه با افزودن پارامتر &notification=true query به cache offline-search-responses اضافه می‌شود، به طوری که وقتی کاربر روی اعلان کلیک می‌کند، می‌توان این ورودی حافظه پنهان را دریافت کرد.

برای ادغام همگام‌سازی پس‌زمینه با سرویس خود، یک استراتژی NetworkOnly برای درخواست‌ها به URL جستجو ( /search_action ) تعریف کنید و bgSyncPlugin از قبل تعریف‌شده را ارسال کنید. کد زیر را به پایین public/sw.js اضافه کنید:

const matchSearchUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return url.pathname === '/search_action' && !(notificationParam === 'true');
};

workbox.routing.registerRoute(
  matchSearchUrl,
  new workbox.strategies.NetworkOnly({
    plugins: [bgSyncPlugin],
  }),
);

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

در مرحله بعد، کد زیر را به پایین public/sw.js اضافه کنید تا یک استراتژی ذخیره سازی برای درخواست های ارسالی از اعلان ها تعریف کنید. از یک استراتژی CacheFirst استفاده کنید، تا بتوان آنها را از کش ارائه کرد.

const matchNotificationUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return (url.pathname === '/search_action' && (notificationParam === 'true'));
};

workbox.routing.registerRoute(matchNotificationUrl,
  new workbox.strategies.CacheFirst({
     cacheName: 'offline-search-responses',
  })
);

در نهایت کد را برای نمایش اعلان ها اضافه کنید:

function showNotification(notificationUrl) {
  if (Notification.permission) {
     self.registration.showNotification('Your search is ready!', {
        body: 'Click to see you search result',
        icon: '/img/workbox.jpg',
        data: {
           url: notificationUrl
        }
     });
  }
}

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
     clients.openWindow(event.notification.data.url)
  );
});

ویژگی را تست کنید

  1. به برگه دیگری که برنامه شما را اجرا می کند، برگردید.
  2. لیست کشویی Throttling را به حالت آنلاین برگردانید.
  3. دکمه بازگشت Chrome را فشار دهید تا به صفحه جستجو برگردید.
  4. دکمه بارگیری مجدد Chrome را به مدت طولانی فشار دهید و برای اطمینان از به‌روزرسانی سرویس‌کارتان ، خالی کردن حافظه پنهان و بارگذاری مجدد سخت را انتخاب کنید.
  5. لیست کشویی Throttling را دوباره به حالت آفلاین برگردانید.
  6. یک عبارت جستجو را وارد کنید و دوباره روی دکمه جستجو کلیک کنید.
  7. روی اشتراک در اعلان‌ها کلیک کنید.
  8. وقتی Chrome از شما می‌پرسد که آیا می‌خواهید به برنامه اجازه ارسال اعلان‌ها را بدهید، روی اجازه کلیک کنید.
  9. عبارت جستجوی دیگری را وارد کنید و دوباره روی دکمه جستجو کلیک کنید.
  10. لیست کشویی Throttling را دوباره روی Online تنظیم کنید.

پس از بازگشت اتصال، یک اعلان نشان داده می شود:

تصویری از جریان آفلاین کامل.

نتیجه گیری

Workbox بسیاری از ویژگی های داخلی را ارائه می دهد تا PWA های شما را انعطاف پذیرتر و جذاب تر کند. در این نرم‌افزار، نحوه پیاده‌سازی Background Sync API را از طریق انتزاع Workbox بررسی کرده‌اید تا اطمینان حاصل شود که درخواست‌های کاربر آفلاین از بین نمی‌روند و پس از بازگشت اتصال می‌توانند دوباره امتحان شوند. نسخه ی نمایشی یک برنامه جستجوی ساده است، اما می توانید از یک پیاده سازی مشابه برای سناریوهای پیچیده تر و موارد استفاده از جمله برنامه های چت، ارسال پیام در یک شبکه اجتماعی و غیره استفاده کنید.

،

این کد لبه به شما نشان می دهد که چگونه یک تجربه جستجوی انعطاف پذیر را با Workbox پیاده سازی کنید. برنامه نمایشی که استفاده می‌کند شامل یک کادر جستجو است که یک نقطه پایانی سرور را فراخوانی می‌کند و کاربر را به یک صفحه HTML اصلی هدایت می‌کند.

اندازه گیری کنید

قبل از افزودن بهینه سازی، همیشه ایده خوبی است که ابتدا وضعیت فعلی برنامه را تجزیه و تحلیل کنید.

  • روی Remix to Edit کلیک کنید تا پروژه قابل ویرایش باشد.
  • برای پیش نمایش سایت، View App را فشار دهید. سپس تمام صفحه را فشار دهید تمام صفحه .

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

  1. «Control+Shift+J» (یا «Command+Option+J» در Mac) را فشار دهید تا DevTools باز شود.
  2. روی تب Network کلیک کنید.
  3. Chrome DevTools را باز کنید و پنل Network را انتخاب کنید.
  4. در لیست کشویی Throttling ، Offline را انتخاب کنید.
  5. در برنامه آزمایشی یک عبارت جستجو را وارد کنید، سپس روی دکمه جستجو کلیک کنید.

صفحه خطای استاندارد مرورگر نشان داده شده است:

تصویری از UX پیش فرض آفلاین در مرورگر.

یک پاسخ بازگشتی ارائه دهید

Service Worker حاوی کدی است که صفحه آفلاین را به لیست پیش کش اضافه می کند، بنابراین همیشه می توان آن را در رویداد install سرویس دهنده ذخیره کرد.

معمولاً باید به Workbox دستور دهید تا این فایل را در زمان ساخت، با ادغام کتابخانه با ابزار ساخت انتخابی خود (به عنوان مثال webpack یا gulp ) به لیست پیش کش اضافه کند.

برای سادگی، ما قبلاً آن را برای شما انجام داده ایم. کد زیر در public/sw.js این کار را انجام می دهد:

const FALLBACK_HTML_URL = '/index_offline.html';

workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

سپس، کدی را برای استفاده از صفحه آفلاین به عنوان پاسخ بازگشتی اضافه کنید:

  1. برای مشاهده منبع، View Source را فشار دهید.
  2. کد زیر را به پایین public/sw.js اضافه کنید:
workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());

workbox.routing.setCatchHandler(({event}) => {
  switch (event.request.destination) {
    case 'document':
      return caches.match(FALLBACK_HTML_URL);
      break;
    default:
      return Response.error();
  }
});

کد زیر را انجام می دهد:

  • یک استراتژی پیش‌فرض Network Only را تعریف می‌کند که برای همه درخواست‌ها اعمال می‌شود.
  • با فراخوانی workbox.routing.setCatchHandler() برای مدیریت درخواست های ناموفق، یک کنترل کننده خطای جهانی را اعلام می کند. هنگامی که درخواست ها برای اسناد هستند، یک صفحه HTML آفلاین بازگشتی برگردانده می شود.

برای تست این عملکرد:

  1. به برگه دیگری که برنامه شما را اجرا می کند، برگردید.
  2. لیست کشویی Throttling را به حالت آنلاین برگردانید.
  3. دکمه بازگشت Chrome را فشار دهید تا به صفحه جستجو برگردید.
  4. مطمئن شوید که چک باکس Disable cache در DevTools غیرفعال است.
  5. دکمه بارگیری مجدد Chrome را به مدت طولانی فشار دهید و برای اطمینان از به‌روزرسانی سرویس‌کارتان ، خالی کردن حافظه پنهان و بارگذاری مجدد سخت را انتخاب کنید.
  6. لیست کشویی Throttling را دوباره به حالت آفلاین برگردانید.
  7. یک عبارت جستجو را وارد کنید و دوباره روی دکمه جستجو کلیک کنید.

صفحه HTML بازگشتی نشان داده شده است:

تصویری از UX آفلاین سفارشی در مرورگر.

درخواست مجوز اعلان

برای سادگی، صفحه آفلاین در views/index_offline.html قبلاً حاوی کد درخواست مجوزهای اعلان در یک بلوک اسکریپت در پایین است:

function requestNotificationPermission(event) {
  event.preventDefault();

  Notification.requestPermission().then(function (result) {
    showOfflineText(result);
  });
}

کد زیر را انجام می دهد:

  • وقتی کاربر روی اشتراک در اعلان‌ها کلیک می‌کند، تابع requestNotificationPermission() فراخوانی می‌شود که Notification.requestPermission() را فراخوانی می‌کند تا درخواست مجوز پیش‌فرض مرورگر را نشان دهد. این قول با مجوز انتخاب شده توسط کاربر حل می شود، که می تواند granted ، denied یا default باشد.
  • مجوز حل شده را به showOfflineText() می دهد تا متن مناسب را به کاربر نشان دهد.

پرس و جوهای آفلاین را ادامه دهید و وقتی آنلاین شدید دوباره امتحان کنید

در مرحله بعد، Workbox Background Sync را برای تداوم پرس و جوهای آفلاین پیاده سازی کنید تا زمانی که مرورگر تشخیص داد که اتصال بازگشته است، آنها را دوباره امتحان کنید.

  1. public/sw.js را برای ویرایش باز کنید.
  2. کد زیر را در انتهای فایل اضافه کنید:
const bgSyncPlugin = new workbox.backgroundSync.Plugin('offlineQueryQueue', {
  maxRetentionTime: 60,
  onSync: async ({queue}) => {
    let entry;
    while ((entry = await queue.shiftRequest())) {
      try {
        const response = await fetch(entry.request);
        const cache = await caches.open('offline-search-responses');
        const offlineUrl = `${entry.request.url}&notification=true`;
        cache.put(offlineUrl, response);
        showNotification(offlineUrl);
      } catch (error) {
        await this.unshiftRequest(entry);
        throw error;
      }
    }
  },
});

کد زیر را انجام می دهد:

  • workbox.backgroundSync.Plugin حاوی منطقی است که درخواست‌های ناموفق را به یک صف اضافه می‌کند تا بعداً دوباره امتحان شوند. این درخواست ها در IndexedDB ادامه خواهند داشت.
  • maxRetentionTime مقدار زمانی را که ممکن است یک درخواست دوباره امتحان شود را نشان می دهد. در این مورد ما 60 دقیقه را انتخاب کرده ایم (پس از آن دور ریخته می شود).
  • onSync مهمترین بخش این کد است. هنگامی که اتصال دوباره برقرار می شود، این تماس برگشتی فراخوانی می شود تا درخواست های در صف بازیابی و سپس از شبکه واکشی شوند.
  • پاسخ شبکه با افزودن پارامتر &notification=true query به cache offline-search-responses اضافه می‌شود، به طوری که وقتی کاربر روی اعلان کلیک می‌کند، می‌توان این ورودی حافظه پنهان را دریافت کرد.

برای ادغام همگام‌سازی پس‌زمینه با سرویس خود، یک استراتژی NetworkOnly برای درخواست‌ها به URL جستجو ( /search_action ) تعریف کنید و bgSyncPlugin از قبل تعریف‌شده را ارسال کنید. کد زیر را به پایین public/sw.js اضافه کنید:

const matchSearchUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return url.pathname === '/search_action' && !(notificationParam === 'true');
};

workbox.routing.registerRoute(
  matchSearchUrl,
  new workbox.strategies.NetworkOnly({
    plugins: [bgSyncPlugin],
  }),
);

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

در مرحله بعد، کد زیر را به پایین public/sw.js اضافه کنید تا یک استراتژی ذخیره سازی برای درخواست های ارسالی از اعلان ها تعریف کنید. از یک استراتژی CacheFirst استفاده کنید، تا بتوان آنها را از کش ارائه کرد.

const matchNotificationUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return (url.pathname === '/search_action' && (notificationParam === 'true'));
};

workbox.routing.registerRoute(matchNotificationUrl,
  new workbox.strategies.CacheFirst({
     cacheName: 'offline-search-responses',
  })
);

در نهایت کد را برای نمایش اعلان ها اضافه کنید:

function showNotification(notificationUrl) {
  if (Notification.permission) {
     self.registration.showNotification('Your search is ready!', {
        body: 'Click to see you search result',
        icon: '/img/workbox.jpg',
        data: {
           url: notificationUrl
        }
     });
  }
}

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
     clients.openWindow(event.notification.data.url)
  );
});

ویژگی را تست کنید

  1. به برگه دیگری که برنامه شما را اجرا می کند، برگردید.
  2. لیست کشویی Throttling را به حالت آنلاین برگردانید.
  3. دکمه بازگشت Chrome را فشار دهید تا به صفحه جستجو برگردید.
  4. دکمه بارگیری مجدد Chrome را به مدت طولانی فشار دهید و برای اطمینان از به‌روزرسانی سرویس‌کارتان ، خالی کردن حافظه پنهان و بارگذاری مجدد سخت را انتخاب کنید.
  5. لیست کشویی Throttling را دوباره به حالت آفلاین برگردانید.
  6. یک عبارت جستجو را وارد کنید و دوباره روی دکمه جستجو کلیک کنید.
  7. روی اشتراک در اعلان‌ها کلیک کنید.
  8. وقتی Chrome از شما می‌پرسد که آیا می‌خواهید به برنامه اجازه ارسال اعلان‌ها را بدهید، روی اجازه کلیک کنید.
  9. عبارت جستجوی دیگری را وارد کنید و دوباره روی دکمه جستجو کلیک کنید.
  10. لیست کشویی Throttling را دوباره روی Online تنظیم کنید.

پس از بازگشت اتصال، یک اعلان نشان داده می شود:

تصویری از جریان آفلاین کامل.

نتیجه گیری

Workbox بسیاری از ویژگی های داخلی را ارائه می دهد تا PWA های شما را انعطاف پذیرتر و جذاب تر کند. در این نرم‌افزار، نحوه پیاده‌سازی Background Sync API را از طریق انتزاع Workbox بررسی کرده‌اید تا اطمینان حاصل شود که درخواست‌های کاربر آفلاین از بین نمی‌روند و پس از بازگشت اتصال می‌توانند دوباره امتحان شوند. نسخه ی نمایشی یک برنامه جستجوی ساده است، اما می توانید از یک پیاده سازی مشابه برای سناریوهای پیچیده تر و موارد استفاده از جمله برنامه های چت، ارسال پیام در یک شبکه اجتماعی و غیره استفاده کنید.