Xử lý các nội dung cập nhật của trình chạy dịch vụ một cách nhanh chóng

Theo mặc định, vòng đời của trình chạy dịch vụ yêu cầu khi tìm thấy và cài đặt trình chạy dịch vụ được cập nhật, tất cả thẻ đang mở mà trình chạy dịch vụ hiện tại đang kiểm soát phải được đóng hoặc trải qua một quá trình điều hướng trước khi trình chạy dịch vụ được cập nhật kích hoạt và nắm quyền kiểm soát.

Trong nhiều trường hợp, bạn có thể cho phép điều này xảy ra đúng lúc, nhưng trong một số trường hợp, bạn có thể muốn thông báo cho người dùng rằng có bản cập nhật của trình chạy dịch vụ đang chờ xử lý, sau đó tự động hoá quá trình chuyển sang trình chạy dịch vụ mới. Để thực hiện việc này, bạn cần phải thêm một số mã vào trang và trình chạy dịch vụ của mình.

Mã để đặt vào trang của bạn

Mã sau đây chạy trong phần tử <script> cùng dòng sử dụng các mô-đun JavaScript được nhập từ phiên bản workbox-window do CDN lưu trữ. Dịch vụ này đăng ký một trình chạy dịch vụ bằng workbox-window và sẽ phản ứng nếu trình chạy dịch vụ này bị mắc kẹt trong giai đoạn chờ. Khi tìm thấy một trình chạy dịch vụ chờ, mã này sẽ thông báo cho người dùng rằng đã có phiên bản cập nhật của trang web và nhắc họ tải lại.

<!-- This script tag uses JavaScript modules, so the proper `type` attribute value is required -->
<script type="module">
  // This code sample uses features introduced in Workbox v6.
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');
    let registration;

    const showSkipWaitingPrompt = async (event) => {
      // Assuming the user accepted the update, set up a listener
      // that will reload the page as soon as the previously waiting
      // service worker has taken control.
      wb.addEventListener('controlling', () => {
        // At this point, reloading will ensure that the current
        // tab is loaded under the control of the new service worker.
        // Depending on your web app, you may want to auto-save or
        // persist transient state before triggering the reload.
        window.location.reload();
      });

      // When `event.wasWaitingBeforeRegister` is true, a previously
      // updated service worker is still waiting.
      // You may want to customize the UI prompt accordingly.

      // This code assumes your app has a promptForUpdate() method,
      // which returns true if the user wants to update.
      // Implementing this is app-specific; some examples are:
      // https://open-ui.org/components/alert.research or
      // https://open-ui.org/components/toast.research
      const updateAccepted = await promptForUpdate();

      if (updateAccepted) {
        wb.messageSkipWaiting();
      }
    };

    // Add an event listener to detect when the registered
    // service worker has installed but is waiting to activate.
    wb.addEventListener('waiting', (event) => {
      showSkipWaitingPrompt(event);
    });

    wb.register();
  }
</script>

Nếu họ chấp nhận, messageSkipWaiting() sẽ yêu cầu nhân viên dịch vụ chờ gọi self.skipWaiting(), nghĩa là dịch vụ này sẽ bắt đầu kích hoạt. Sau khi được kích hoạt, trình chạy dịch vụ mới sẽ kiểm soát mọi ứng dụng hiện có, kích hoạt sự kiện controlling trong workbox-window. Khi điều này xảy ra, trang hiện tại sẽ tải lại bằng phiên bản mới nhất của tất cả thành phần được lưu trước trong bộ nhớ đệm và mọi logic định tuyến mới có trong trình chạy dịch vụ đã cập nhật.

Mã để đưa vào trình chạy dịch vụ

Sau khi có được mã từ phần trước trong trang của mình, bạn cần thêm một số mã vào trình chạy dịch vụ để trình chạy dịch vụ biết thời điểm bỏ qua giai đoạn chờ. Nếu bạn đang sử dụng generateSW từ workbox-build và đã đặt tuỳ chọn skipWaiting thành false (mặc định) thì bạn đã sẵn sàng, vì mã bên dưới sẽ tự động được đưa vào tệp trình chạy dịch vụ được tạo của bạn.

Nếu đang viết trình chạy dịch vụ của riêng mình (có thể kết hợp với một trong các công cụ xây dựng của Workbox ở chế độ injectManifest) thì bạn cần tự thêm mã sau:

addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

Thao tác này sẽ theo dõi các tin nhắn gửi đến trình chạy dịch vụ từ workbox-window với giá trị typeSKIP_WAITING và khi việc đó xảy ra, sẽ gọi self.skipWaiting(). Phương thức messageSkipWaiting() trong workbox-window, được hiển thị trong mã mẫu trước đó, chịu trách nhiệm gửi thông báo này.

Bạn có cần hiển thị câu lệnh không?

Đây không phải là mẫu mà mọi ứng dụng triển khai trình chạy dịch vụ đều cần tuân theo. Dành cho các trường hợp chọn lọc khi không cung cấp cơ hội tải lại trang trong bản cập nhật trình chạy dịch vụ có thể gây ra các hành vi không mong muốn. Không có quy tắc khó khăn và nhanh chóng nào về việc bạn có nên hiển thị lời nhắc tải lại hay không, nhưng sau đây là một vài trường hợp có thể hợp lý:

  • Bạn thường sử dụng tính năng lưu trữ trước. Đối với thành phần tĩnh, bạn có thể gặp vấn đề sau này nếu sử dụng chiến lược ưu tiên mạng hoặc chiến lược chỉ dành cho mạng cho các yêu cầu điều hướng, chứ không phải chiến lược tải từng phần. Điều này có thể gây ra trường hợp các thành phần được tạo phiên bản có thể thay đổi và trình chạy dịch vụ không lưu trước các thành phần đó vào bộ nhớ đệm. Việc cung cấp nút tải lại ở đây có thể giúp tránh một số hành vi không mong muốn.
  • Nếu bạn đang phân phát HTML được lưu trước trong bộ nhớ đệm. Trong trường hợp này, bạn đặc biệt nên cân nhắc việc cung cấp nút tải lại trên các bản cập nhật của trình chạy dịch vụ, vì các bản cập nhật cho HTML đó sẽ không được nhận dạng cho đến khi trình chạy dịch vụ được cập nhật nắm quyền kiểm soát.
  • Nếu bạn không chủ yếu dựa vào việc lưu vào bộ nhớ đệm trong thời gian chạy. Khi lưu tài nguyên vào bộ nhớ đệm trong thời gian chạy, bạn không cần phải cho người dùng biết họ cần tải lại. Khi các thành phần được tạo phiên bản thay đổi, chúng sẽ được thêm vào bộ nhớ đệm của thời gian chạy đúng lúc – giả sử các yêu cầu điều hướng sử dụng chiến lược ưu tiên mạng hoặc chỉ mạng.
  • Khi sử dụng chiến lược cũ trong khi xác thực lại, bạn có thể cân nhắc sử dụng mô-đun workbox-broadcast-update để thông báo cho người dùng về các nội dung cập nhật của trình chạy dịch vụ.

Việc bạn có cần thông báo cho người dùng về các bản cập nhật của một trình chạy dịch vụ hay không tuỳ thuộc vào ứng dụng của bạn cũng như các yêu cầu riêng của ứng dụng đó. Nếu bạn phát hiện người dùng của mình đang gặp phải những hành vi lạ khi bạn đẩy ra một trình chạy dịch vụ mới, đó có thể là tín hiệu tốt nhất mà bạn nên thông báo cho họ.