Xây dựng trải nghiệm tìm kiếm linh hoạt với Workbox

Demián Renzulli
Demián Renzulli
Jeff Posnick
Jeff Posnick

Lớp học lập trình này cho bạn biết cách triển khai trải nghiệm tìm kiếm linh hoạt bằng Workbox. Ứng dụng minh hoạ mà ứng dụng này sử dụng chứa một hộp tìm kiếm để gọi điểm cuối của máy chủ và chuyển hướng người dùng đến một trang HTML cơ bản.

Đo

Trước khi thêm tối ưu hoá, bạn nên phân tích trạng thái hiện tại của ứng dụng trước.

  • Nhấp vào Phối lại để chỉnh sửa để có thể chỉnh sửa dự án.
  • Để xem trước trang web, hãy nhấn vào Xem ứng dụng. Sau đó nhấn Toàn màn hình toàn màn hình.

Trong thẻ mới vừa mở ra, hãy kiểm tra cách trang web hoạt động khi không có kết nối mạng:

  1. Nhấn tổ hợp phím "Control + Shift + J" (hoặc "Command+Option+J" trên máy Mac) để mở Công cụ cho nhà phát triển.
  2. Nhấp vào thẻ Mạng.
  3. Mở Công cụ của Chrome cho nhà phát triển rồi chọn bảng điều khiển Mạng.
  4. Trong danh sách thả xuống Điều tiết, chọn Khi không có mạng.
  5. Trong ứng dụng minh hoạ, hãy nhập một cụm từ tìm kiếm rồi nhấp vào nút Tìm kiếm.

Trang lỗi trình duyệt chuẩn hiển thị:

Ảnh chụp màn hình giao diện người dùng ngoại tuyến mặc định trên trình duyệt.

Cung cấp phản hồi dự phòng

Service worker chứa mã để thêm trang ngoại tuyến vào danh sách bộ nhớ đệm trước để nó luôn có thể được lưu vào bộ nhớ đệm tại sự kiện install của trình chạy dịch vụ.

Thông thường, bạn cần hướng dẫn Workbox thêm tệp này vào danh sách bộ nhớ đệm trước tại thời điểm xây dựng, bằng cách tích hợp thư viện với công cụ xây dựng mà bạn lựa chọn (ví dụ: webpack hoặc gulp).

Để đơn giản hoá, chúng tôi đã thực hiện việc này cho bạn. Mã sau đây tại public/sw.js sẽ thực hiện việc đó:

const FALLBACK_HTML_URL = '/index_offline.html';

workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

Tiếp theo, hãy thêm mã để sử dụng trang ngoại tuyến làm phản hồi dự phòng:

  1. Để xem nguồn, hãy nhấn vào Xem nguồn.
  2. Thêm mã sau vào cuối 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();
  }
});

Đoạn mã này sẽ thực hiện những việc sau:

  • Xác định chiến lược Chỉ mạng mặc định sẽ áp dụng cho tất cả các yêu cầu.
  • Khai báo một trình xử lý lỗi chung bằng cách gọi workbox.routing.setCatchHandler() để quản lý các yêu cầu không thực hiện được. Khi yêu cầu dành cho tài liệu, một trang HTML ngoại tuyến dự phòng sẽ được trả về.

Cách kiểm thử chức năng này:

  1. Quay lại thẻ khác đang chạy ứng dụng của bạn.
  2. Đặt danh sách thả xuống Điều tiết thành Trực tuyến.
  3. Nhấn vào nút Quay lại của Chrome để quay lại trang tìm kiếm.
  4. Đảm bảo rằng bạn đã tắt hộp đánh dấu Tắt bộ nhớ đệm trong Công cụ cho nhà phát triển.
  5. Nhấn và giữ nút Tải lại của Chrome rồi chọn Làm trống bộ nhớ đệm và tải lại cứng để đảm bảo trình chạy dịch vụ của bạn được cập nhật.
  6. Đặt lại danh sách thả xuống Điều tiết thành Ngoại tuyến.
  7. Nhập cụm từ tìm kiếm rồi nhấp lại vào nút Tìm kiếm.

Trang HTML dự phòng sẽ hiển thị:

Ảnh chụp màn hình trải nghiệm người dùng ngoại tuyến tuỳ chỉnh trên trình duyệt.

Yêu cầu cấp quyền gửi thông báo

Để đơn giản, trang ngoại tuyến tại views/index_offline.html đã chứa đoạn mã để yêu cầu quyền gửi thông báo trong khối tập lệnh ở dưới cùng:

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

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

Đoạn mã này sẽ thực hiện những việc sau:

  • Khi người dùng nhấp vào đăng ký nhận thông báo, hàm requestNotificationPermission() sẽ được gọi (gọi Notification.requestPermission()) để hiển thị l��i nhắc cấp quyền mặc định của trình duyệt. Lời hứa sẽ được phân giải với quyền do người dùng chọn, có thể là granted, denied hoặc default.
  • Chuyển quyền đã giải quyết cho showOfflineText() để hiện văn bản thích hợp cho người dùng.

Duy trì truy vấn ngoại tuyến rồi thử lại khi có kết nối mạng trở lại

Tiếp theo, hãy triển khai tính năng Đồng bộ hoá nền hộp làm việc để duy trì các truy vấn ngoại tuyến. Khi trình duyệt phát hiện thấy kết nối đã hoạt động trở lại, bạn có thể thử lại các truy vấn này.

  1. Mở public/sw.js để chỉnh sửa.
  2. Thêm mã sau vào cuối tệp:
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;
      }
    }
  },
});

Đoạn mã này sẽ thực hiện những việc sau:

  • workbox.backgroundSync.Plugin chứa logic để thêm các yêu cầu không thành công vào hàng đợi để bạn có thể thử lại sau. Các yêu cầu này sẽ được duy trì trong IndexedDB.
  • maxRetentionTime cho biết khoảng thời gian có thể thử lại một yêu cầu. Trong trường hợp này, chúng ta đã chọn 60 phút (sau thời gian này sẽ bị loại bỏ).
  • onSync là phần quan trọng nhất của mã này. Lệnh gọi lại này sẽ được gọi khi có kết nối trở lại để truy xuất các yêu cầu trong hàng đợi rồi tìm nạp từ mạng.
  • Phản hồi mạng được thêm vào bộ nhớ đệm offline-search-responses, thêm tham số truy vấn &notification=true để có thể chọn mục nhập bộ nhớ đệm này khi người dùng nhấp vào thông báo.

Để tích hợp tính năng đồng bộ hoá ở chế độ nền với dịch vụ, hãy xác định chiến lược NetworkOnly cho các yêu cầu đến URL tìm kiếm (/search_action) và truyền bgSyncPlugin được xác định trước đó. Thêm mã sau vào cuối 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],
  }),
);

Thao tác này sẽ yêu cầu Workbox luôn truy cập mạng và khi yêu cầu không thành công, hãy sử dụng logic đồng bộ hoá ở chế độ nền.

Tiếp theo, hãy thêm mã sau vào cuối public/sw.js để xác định chiến lược lưu vào bộ nhớ đệm cho các yêu cầu đến từ thông báo. Sử dụng chiến lược CacheFirst để có thể phân phát các thành phần này từ bộ nhớ đệm.

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',
  })
);

Cuối cùng, hãy thêm mã để hiển thị thông báo:

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

Thử nghiệm tính năng

  1. Quay lại thẻ khác đang chạy ứng dụng của bạn.
  2. Đặt danh sách thả xuống Điều tiết thành Trực tuyến.
  3. Nhấn vào nút Quay lại của Chrome để quay lại trang tìm kiếm.
  4. Nhấn và giữ nút Tải lại của Chrome rồi chọn Làm trống bộ nhớ đệm và tải lại cứng để đảm bảo trình chạy dịch vụ của bạn được cập nhật.
  5. Đặt lại danh sách thả xuống Điều tiết thành Ngoại tuyến.
  6. Nhập cụm từ tìm kiếm rồi nhấp lại vào nút Tìm kiếm.
  7. Nhấp vào đăng ký nhận thông báo.
  8. Khi Chrome hỏi bạn có muốn cấp quyền gửi thông báo cho ứng dụng không, hãy nhấp vào Cho phép.
  9. Nhập một cụm từ tìm kiếm khác rồi nhấp lại vào nút Tìm kiếm.
  10. Đặt lại danh sách thả xuống Điều tiết thành Trực tuyến.

Sau khi kết nối trở lại, bạn sẽ thấy một thông báo:

Ảnh chụp màn hình toàn bộ quy trình hoạt động khi không có mạng.

Kết luận

Workbox cung cấp nhiều tính năng tích hợp sẵn giúp PWA của bạn hoạt động ổn định và hấp dẫn hơn. Trong lớp học lập trình này, bạn đã tìm hiểu cách triển khai API Đồng bộ hoá dưới nền thông qua bản tóm tắt của Workbox, nhằm đảm bảo các truy vấn ngoại tuy���n của người dùng không bị mất và có thể thử lại sau khi kết nối trở lại. Bản minh hoạ là một ứng dụng tìm kiếm đơn giản, nhưng bạn có thể sử dụng cách triển khai tương tự cho các tình huống và trường hợp sử dụng phức tạp hơn, bao gồm cả ứng dụng nhắn tin, đăng tin nhắn lên mạng xã hội, v.v.