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

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

วัดระยะทาง

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

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

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

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

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

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

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

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

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

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

ภาพหน้าจอของกระบวนการออฟไลน์เต็มรูปแบบ

บทสรุป

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