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 một trình chạy dịch vụ được cập nhật, tất cả các thẻ đang mở mà trình chạy dịch vụ hiện đang kiểm soát phải được đóng hoặc trải qua quá trình điều hướng trước khi trình chạy dịch vụ 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 trong thời gian tới. Tuy nhiên, trong một số trường hợp, bạn có thể 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 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 được lưu trữ trên CDN. Dịch vụ này đăng ký một trình chạy dịch vụ bằng workbox-window và sẽ phản hồi nếu trình chạy này bị kẹt trong giai đoạn chờ. Khi tìm thấy một trình chạy dịch vụ đang 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 chấp nhận, messageSkipWaiting() sẽ yêu cầu trình chạy dịch vụ chờ gọi self.skipWaiting(), nghĩa là trình chạy này sẽ bắt đầu kích hoạt. Sau khi 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ó và 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ả các tài sản được lưu trước vào 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 nhận được mã từ phần trước trên trang, bạn cần thêm một số mã vào trình chạy dịch vụ để cho trình chạy biết thời điểm bỏ qua giai đoạn chờ. Nếu đang sử dụng generateSW qua workbox-build và đã đặt tuỳ chọn skipWaiting thành false (mặc định), thì bạn có thể tiếp tục sử dụng vì mã bên dưới sẽ tự động được đưa vào tệp trình chạy dịch vụ đã tạo.

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ụ tạo của Workbox) ở chế độ injectManifest, 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 thông báo được gửi đến trình chạy dịch vụ từ workbox-window với giá trị typeSKIP_WAITING và khi điều đó xảy ra, hãy gọi self.skipWaiting(). Phương thức messageSkipWaiting() trong workbox-window, 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ị lời nhắc không?

Đây không phải là mẫu mà mọi ứng dụng triển khai một trình chạy dịch vụ đều cần tuân theo. Danh sách này dành cho một số trường hợp mà trong đó việc không cung cấp cơ hội tải lại trang khi cập nhật trình chạy dịch vụ có thể dẫn đến các hành vi không mong muốn. Không có quy tắc cố định 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 tình huống có thể hợp lý:

  • Bạn sử dụng tính năng lưu vào bộ nhớ đệm một cách rộng rãi. Với tài sả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 chỉ sử dụng mạng cho các yêu cầu điều hướng, nhưng lại tải từng phần của tài sản tĩnh. Đ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à một trình chạy dịch vụ chưa lưu trước các thành phần này vào bộ nhớ đệm. Việc cung cấp một nút tải lại tạ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 nên cân nhắc việc cung cấp nút tải lại khi cập nhật trình chạy dịch vụ, vì 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 phụ thuộc chủ yếu vào tính năng 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 cho người dùng biết rằng 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 trong thời gian chạy đúng hạn — 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 lỗi thời 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 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 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ư yêu cầu riêng của ứng dụng. Nếu bạn nhận thấy người dùng đang gặp phải những hành vi khác thường khi bạn triển khai một trình chạy dịch vụ mới, thì đó có lẽ là tín hiệu tốt nhất mà bạn nên thông báo cho họ.