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

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

วัดผล

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

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

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

  1. กด `Control+Shift+J` (หรือ `Command+Option+J` ใน Mac) เพื่อเปิด DevTools
  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 ค้างไว้ แล้วเลือก ล้างแคชและโหลดซ้ำอย่างละเอียด เพื่อให้มั่นใจว่ามีการอัปเดต 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() เพื่อแสดงข้อความแจ้งขอสิทธิ์เริ่มต้นของเบราว์เซอร์ Promise จะได้รับการแก้ไขด้วยสิทธิ์ที่ผู้ใช้เลือก ซึ่งอาจเป็น 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 เป็นส่วนที่สำคัญที่สุดของโค้ดนี้ ระบบจะเรียกใช้ 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 ค้างไว้ แล้วเลือก ล้างแคชและโหลดซ้ำอย่างละเอียด เพื่อให้มั่นใจว่ามีการอัปเดต Service Worker
  5. ตั้งค่ารายการแบบเลื่อนลงการควบคุมอัตรากลับเป็นออฟไลน์อีกครั้ง
  6. ป้อนคำค้นหา แล้วคลิกปุ่มค้นหาอีกครั้ง
  7. คลิกสมัครรับการแจ้งเตือน
  8. เมื่อ Chrome ถามว่าคุณต้องการให้สิทธิ์แอปในการส่งการแจ้งเตือนหรือไม่ ให้คลิกอนุญาต
  9. ป้อนคำค้นหาอื่น แล้วคลิกปุ่มค้นหาอีกครั้ง
  10. ตั้งค่ารายการแบบเลื่อนลงการควบคุมอัตรากลับเป็นออนไลน์อีกครั้ง

เมื่อกลับมาเชื่อมต่อได้อีกครั้ง การแจ้งเตือนจะปรากฏขึ้น

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

บทสรุป

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