สร้างประสบการณ์การค้นหาที่ยืดหยุ่นด้วย Workbox

Codelab นี้จะแสดงวิธีใช้ประสบการณ์การค้นหาที่ยืดหยุ่นด้วย Workbox แอปเดโมที่แอปใช้มีช่องค้นหาที่เรียกปลายทางเซิร์ฟเวอร์ และเปลี่ยนเส้นทางผู้ใช้ไปยังหน้า HTML พื้นฐาน

วัดระยะทาง

ก่อนที่จะเพิ่มการเพิ่มประสิทธิภาพ คุณควรวิเคราะห์สถานะปัจจุบันของแอปพลิเคชันก่อน

  • คลิกรีมิกซ์เพื่อแก้ไขเพื่อทำให้โปรเจ็กต์แก้ไขได้
  • หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกด เต็มหน้าจอ เต็มหน้าจอ

ในแท็บใหม่ที่เพิ่งเปิดขึ้น ให้ตรวจสอบลักษณะการทำงานของเว็บไซต์เมื่อออฟไลน์ ดังนี้

  1. กด "Control+Shift+J" (หรือ "Command+Option+J" ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาเว็บ
  2. คลิกแท็บเครือข่าย
  3. เปิดเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome และเลือกแผงเครือข่าย
  4. ในรายการแบบเลื่อนลงการควบคุม ให้เลือกออฟไลน์
  5. ในแอปเดโม ให้ป้อนคำค้นหาแล้วคลิกปุ่มค้นหา

หน้าข้อผิดพลาดมาตรฐานของเบราว์เซอร์จะปรากฏขึ้นดังนี้

ภาพหน้าจอของ UX เริ่มต้นแบบออฟไลน์ในเบราว์เซอร์

ระบุการตอบกลับสำรอง

Service Worker มีโค้ดสำหรับเพิ่มหน้าออฟไลน์ไปยังรายการแคชล่วงหน้า ดังนั้นจึงสามารถแคชไว้ในเหตุการณ์ install ของ Service Worker ได้ทุกเมื่อ

โดยปกติแล้วคุณจะต้องสั่งให้ Workbox เพิ่มไฟล์นี้ไปยังรายการแคชล่วงหน้าในเวลาสร้าง โดยการผสานรวมไลบรารีเข้ากับเครื่องมือสร้างที่คุณต้องการ (เช่น webpack หรือ gulp)

เราได้ดำเนินการให้คุณแล้วเพื่อความสะดวก โค้ดต่อไปนี้ที่ public/sw.js ดำเนินการดังกล่าวได้

const FALLBACK_HTML_URL = '/index_offline.html';

workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

จากนั้น เพิ่มโค้ดเพื่อใช้หน้าออฟไลน์เป็นการตอบสนองสำรองดังนี้

  1. หากต้องการดูแหล่งที่มา ให้กดดูแหล่งที่มา
  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();
  }
});

โค้ดมีการทำงานดังนี้

  • กำหนดกลยุทธ์เฉพาะเครือข่ายเริ่มต้นที่จะมีผลกับคำขอทั้งหมด
  • ประกาศเครื่องจัดการข้อผิดพลาดส่วนกลางโดยการเรียกใช้ workbox.routing.setCatchHandler() เพื่อจัดการคำขอที่ล้มเหลว เมื่อเป็นคำขอสำหรับเอกสาร ระบบจะแสดงหน้า HTML ออฟไลน์สำรอง

วิธีทดสอบฟังก์ชันการทำงานนี้

  1. กลับไปยังแท็บอื่นที่กำลังใช้งานแอปของคุณ
  2. ตั้งค่ารายการแบบเลื่อนลงการควบคุมกลับไปเป็นออนไลน์
  3. กดปุ่มกลับของ Chrome เพื่อกลับไปยังหน้าค้นหา
  4. ตรวจสอบว่าช่องทำเครื่องหมายปิดใช้แคชในเครื่องมือสำหรับนักพัฒนาเว็บปิดอยู่
  5. กดปุ่มโหลดซ้ำของ Chrome ค้างไว้และเลือก ล้างแคชและโหลดซ้ำถาวร เพื่อให้แน่ใจว่าได้อัปเดตโปรแกรมทำงานของบริการแล้ว
  6. ตั้งค่ารายการแบบเลื่อนลงการควบคุมกลับไปเป็นออฟไลน์อีกครั้ง
  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 เพื่อเก็บการค้นหาแบบออฟไลน์ไว้ เพื่อที่จะสามารถลองอีกครั้งเมื่อเบราว์เซอร์ตรวจพบว่าการเชื่อมต่อกลับมาแล้ว

  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 คือส่วนที่สำคัญที่สุดของโค้ดนี้ ระบบจะเรียก Callback นี้เมื่อมีการเชื่อมต่ออีกครั้งเพื่อให้มีการเรียกคำขอที่อยู่ในคิวแล้วดึงข้อมูลจากเครือข่าย
  • ระบบจะเพิ่มการตอบสนองของเครือข่ายลงในแคช offline-search-responses โดยเพิ่มพารามิเตอร์การค้นหาของ &notification=true ต่อท้าย เพื่อให้ระบบรับรายการแคชนี้ได้เมื่อผู้ใช้คลิกการแจ้งเตือน

ในการผสานรวมการซิงค์ในเบื้องหลังกับบริการของคุณ ให้กำหนดกลยุทธ์ 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. ตั้งค่ารายการแบบเลื่อนลงการควบคุมกลับไปเป็นออนไลน์
  3. กดปุ่มกลับของ Chrome เพื่อกลับไปยังหน้าค้นหา
  4. กดปุ่มโหลดซ้ำของ Chrome ค้างไว้และเลือก ล้างแคชและโหลดซ้ำถาวร เพื่อให้แน่ใจว่าได้อัปเดตโปรแกรมทำงานของบริการแล้ว
  5. ตั้งค่ารายการแบบเลื่อนลงการควบคุมกลับไปเป็นออฟไลน์อีกครั้ง
  6. ป้อนคำค้นหาแล้วคลิกปุ่มค้นหาอีกครั้ง
  7. คลิกสมัครรับการแจ้งเตือน
  8. เมื่อ Chrome ถามคุณว่าต้องการให้สิทธิ์แอปในส่งการแจ้งเตือนไหม ให้คลิกอนุญาต
  9. ป้อนคำค้นหาอื่นแล้วคลิกปุ่มค้นหาอีกครั้ง
  10. ตั้งค่ารายการแบบเลื่อนลงการควบคุมกลับไปเป็นออนไลน์อีกครั้ง

เมื่อการเชื่อมต่อกลับมาแล้ว ระบบจะแสดงการแจ้งเตือนดังนี้

ภาพหน้าจอของขั้นตอนออฟไลน์ทั้งหมด

บทสรุป

Workbox มีฟีเจอร์ในตัวมากมายที่จะช่วยให้ PWA มีความยืดหยุ่นและน่าสนใจมากขึ้น ใน Codelab นี้ คุณได้สำรวจวิธีใช้ Background Sync API โดยใช้กระบวนการ Abstraction ของ Workbox เพื่อให้แน่ใจว่าคำค้นหาของผู้ใช้แบบออฟไลน์จะไม่สูญหาย และสามารถลองอีกครั้งได้เมื่อการเชื่อมต่อกลับมาแล้ว การสาธิตนี้เป็นแอปค้นหาที่เรียบง่าย แต่คุณสามารถใช้งานในลักษณะเดียวกันสำหรับสถานการณ์และกรณีการใช้งานที่ซับซ้อนมากขึ้นได้ เช่น แอปแชท การโพสต์ข้อความในโซเชียลเน็ตเวิร์ก เป็นต้น