cửa sổ hộp làm việc

Gói workbox-window là một tập hợp các mô-đun dự định chạy trong ngữ cảnh window, tức là bên trong các trang web của bạn. Chúng bổ sung cho các gói hộp công việc khác chạy trong trình chạy dịch vụ.

Các tính năng/mục tiêu chính của workbox-window là:

Nhập và sử dụng cửa sổ hộp làm việc

Điểm truy cập chính cho gói workbox-window là lớp Workbox và bạn có thể nhập gói này vào mã của mình từ CDN của chúng tôi hoặc sử dụng bất kỳ công cụ gói JavaScript phổ biến nào.

Dùng CDN của chúng tôi

Cách dễ nhất để nhập lớp Workbox trên trang web của bạn là từ CDN của chúng tôi:

<script type="module">
  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');

    wb.register();
  }
</script>

Xin lưu ý rằng ví dụ này sử dụng <script type="module"> và câu lệnh import để tải lớp Workbox. Mặc dù bạn có thể cho rằng mình cần chuyển mã này để mã hoạt động được trên các trình duyệt cũ, nhưng điều đó thực sự không cần thiết.

Tất cả các trình duyệt chính có trình chạy dịch vụ cũng hỗ trợ mô-đun JavaScript gốc. Vì vậy, hoàn toàn không có vấn đề gì khi phân phát mã này cho mọi trình duyệt (các trình duyệt cũ sẽ bỏ qua mã này).

Tải Workbox bằng các trình đóng gói JavaScript

Mặc dù hoàn toàn không cần công cụ nào để sử dụng workbox-window, nhưng nếu cơ sở hạ tầng phát triển của bạn đã bao gồm một trình đóng gói như webpack hoặc Rollup hoạt động với các phần phụ thuộc npm, thì bạn có thể sử dụng chúng để tải workbox-window.

Bước đầu tiên là cài đặt workbox-window dưới dạng phần phụ thuộc của ứng dụng:

npm install workbox-window

Sau đó, tại một trong các tệp JavaScript của ứng dụng, hộp làm việc import bằng cách tham chiếu tên gói workbox-window:

import {Workbox} from 'workbox-window';

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

  wb.register();
}

Nếu trình đóng gói của bạn hỗ trợ tính năng phân tách mã thông qua câu lệnh nhập động, thì bạn cũng có thể tải workbox-window theo điều kiện để giúp giảm kích thước gói chính của trang.

Mặc dù workbox-window khá nhỏ, nhưng không có lý do gì để bạn cần tải logic ứng dụng cốt lõi của trang web, vì về bản chất, trình chạy dịch vụ là một tính năng nâng cao tăng dần.

if ('serviceWorker' in navigator) {
  const {Workbox} = await import('workbox-window');

  const wb = new Workbox('/sw.js');
  wb.register();
}

Các khái niệm nâng cao về gói

Không giống như các gói Workbox chạy trong trình chạy dịch vụ, các tệp bản dựng được tham chiếu bởi các trường mainmodule của workbox-window trong package.json sẽ được sao chép sang ES5. Điều này giúp các lớp này tương thích với các công cụ xây dựng hiện nay — một số công cụ không cho phép nhà phát triển chuyển đổi bất kỳ phần phụ thuộc node_module nào.

Nếu hệ thống xây dựng cho phép bạn chuyển mã các phần phụ thuộc (hoặc nếu bạn không cần chuyển mã bất kỳ mã nào), thì bạn nên nhập một tệp nguồn cụ thể thay vì nhập chính gói đó.

Dưới đây là nhiều cách mà bạn có thể nhập Workbox, cùng với nội dung giải thích về nội dung mà mỗi cách sẽ trả về:

// Imports a UMD version with ES5 syntax
// (pkg.main: "build/workbox-window.prod.umd.js")
const {Workbox} = require('workbox-window');

// Imports the module version with ES5 syntax
// (pkg.module: "build/workbox-window.prod.es5.mjs")
import {Workbox} from 'workbox-window';

// Imports the module source file with ES2015+ syntax
import {Workbox} from 'workbox-window/Workbox.mjs';

Ví dụ

Sau khi nhập lớp Workbox, bạn có thể sử dụng lớp này để đăng ký và tương tác với trình chạy dịch vụ. Dưới đây là một số ví dụ về cách bạn có thể dùng Workbox trong ứng dụng:

Đăng ký trình chạy dịch vụ và thông báo cho người dùng lần đầu tiên trình chạy dịch vụ đó hoạt động

Nhiều trình chạy dịch vụ người dùng của ứng dụng web dùng để lưu trước các tài sản vào bộ nhớ đệm để ứng dụng của họ hoạt động ngoại tuyến trong những lần tải trang tiếp theo. Trong một số trường hợp, bạn nên thông báo cho người dùng rằng ứng dụng hiện có thể dùng khi không có mạng.

const wb = new Workbox('/sw.js');

wb.addEventListener('activated', event => {
  // `event.isUpdate` will be true if another version of the service
  // worker was controlling the page when this version was registered.
  if (!event.isUpdate) {
    console.log('Service worker activated for the first time!');

    // If your service worker is configured to precache assets, those
    // assets should all be available now.
  }
});

// Register the service worker after event listeners have been added.
wb.register();

Thông báo cho người dùng nếu trình chạy dịch vụ đã cài đặt nhưng bị treo khi chờ kích hoạt

Khi một trang do một trình chạy dịch vụ hiện có kiểm soát đăng ký một trình chạy dịch vụ mới, theo mặc định, trình chạy dịch vụ đó sẽ không kích hoạt cho đến khi tất cả ứng dụng do trình chạy dịch vụ ban đầu kiểm soát đã huỷ tải hoàn toàn.

Đây là một nguồn gây nhầm lẫn phổ biến cho các nhà phát triển, đặc biệt trong trường hợp tải lại trang hiện tại không khiến trình chạy dịch vụ mới kích hoạt.

Để giảm thiểu nhầm lẫn và làm rõ thời điểm xảy ra tình huống này, lớp Workbox sẽ cung cấp một sự kiện waiting mà bạn có thể theo dõi:

const wb = new Workbox('/sw.js');

wb.addEventListener('waiting', event => {
  console.log(
    `A new service worker has installed, but it can't activate` +
      `until all tabs running the current version have fully unloaded.`
  );
});

// Register the service worker after event listeners have been added.
wb.register();

Thông báo cho người dùng về các bản cập nhật bộ nhớ đệm từ gói workbox-broadcast-update

Gói workbox-broadcast-update là một cách tuyệt vời để có thể phân phát nội dung từ bộ nhớ đệm (để phân phối nhanh), đồng thời có thể thông báo cho người dùng về các bản cập nhật đối với nội dung đó (bằng cách sử dụng chiến lược lỗi thời trong khi xác thực lại).

Để nhận những thông tin cập nhật đó từ cửa sổ, bạn có thể theo dõi các sự kiện message thuộc loại CACHE_UPDATED:

const wb = new Workbox('/sw.js');

wb.addEventListener('message', event => {
  if (event.data.type === 'CACHE_UPDATED') {
    const {updatedURL} = event.data.payload;

    console.log(`A newer version of ${updatedURL} is available!`);
  }
});

// Register the service worker after event listeners have been added.
wb.register();

Gửi cho trình chạy dịch vụ danh sách các URL cần lưu vào bộ nhớ đệm

Đối với một số ứng dụng, có thể bạn sẽ biết tất cả tài sản cần được lưu trước vào bộ nhớ đệm tại thời điểm xây dựng. Tuy nhiên, một số ứng dụng lại phân phát các trang hoàn toàn khác, dựa trên URL mà người dùng truy cập đầu tiên.

Đối với các ứng dụng thuộc danh mục thứ hai, có thể chỉ nên lưu vào bộ nhớ đệm những thành phần mà người dùng cần cho trang cụ thể mà họ đã truy cập. Khi sử dụng gói workbox-routing, bạn có thể gửi cho bộ định tuyến danh sách các URL cần lưu vào bộ nhớ đệm và bộ định tuyến sẽ lưu các URL đó vào bộ nhớ đệm theo các quy tắc được xác định trên chính bộ định tuyến đó.

Ví dụ này sẽ gửi danh sách các URL được trang tải tới bộ định tuyến bất cứ khi nào một trình chạy dịch vụ mới được kích hoạt. Lưu ý, bạn có thể gửi tất cả URL vì chỉ các URL khớp với một tuyến đã xác định trong trình chạy dịch vụ mới được lưu vào bộ nhớ đệm:

const wb = new Workbox('/sw.js');

wb.addEventListener('activated', event => {
  // Get the current page URL + all resources the page loaded.
  const urlsToCache = [
    location.href,
    ...performance.getEntriesByType('resource').map(r => r.name),
  ];
  // Send that list of URLs to your router in the service worker.
  wb.messageSW({
    type: 'CACHE_URLS',
    payload: {urlsToCache},
  });
});

// Register the service worker after event listeners have been added.
wb.register();

Các khoảnh khắc quan trọng trong vòng đời của trình chạy dịch vụ

Vòng đời trình chạy dịch vụ rất phức tạp và có thể là một thách thức để hiểu rõ toàn bộ. Một phần lý do khiến hoạt động này phức tạp là do ứng dụng phải xử lý tất cả trường hợp hiếm gặp cho mọi trường hợp sử dụng có thể có của trình chạy dịch vụ (ví dụ: đăng ký nhiều trình chạy dịch vụ, đăng ký nhiều trình chạy dịch vụ trong các khung khác nhau, đăng ký trình chạy dịch vụ bằng nhiều tên, v.v.).

Tuy nhiên, hầu hết các nhà phát triển triển khai trình chạy dịch vụ không cần phải lo lắng về tất cả các trường hợp hiếm gặp này vì cách sử dụng chúng khá đơn giản. Hầu hết nhà phát triển chỉ đăng ký một trình chạy dịch vụ cho mỗi lượt tải trang và họ không thay đổi tên của tệp trình chạy dịch vụ mà họ triển khai cho máy chủ của mình.

Lớp Workbox có chế độ xem đơn giản hơn này cho vòng đời của trình chạy dịch vụ bằng cách chia nhỏ tất cả các lượt đăng ký của trình chạy dịch vụ thành hai danh mục: trình chạy dịch vụ đã đăng ký của thực thể và một trình chạy dịch vụ bên ngoài:

  • Trình chạy dịch vụ đã đăng ký: một trình chạy dịch vụ bắt đầu cài đặt do thực thể Workbox gọi register() hoặc trình chạy dịch vụ đang hoạt động nếu việc gọi register() không kích hoạt sự kiện updatefound khi đăng ký.
  • Trình chạy dịch vụ bên ngoài: một trình chạy dịch vụ đã bắt đầu cài đặt độc lập với thực thể Workbox gọi register(). Điều này thường xảy ra khi người dùng mở một phiên bản mới của trang web trong một thẻ khác. Khi một sự kiện bắt nguồn từ một trình chạy dịch vụ bên ngoài, thuộc tính isExternal của sự kiện sẽ được đặt thành true.

Với 2 loại trình chạy dịch vụ này, dưới đây là bảng chi tiết về tất cả các khoảnh khắc quan trọng trong vòng đời của trình chạy dịch vụ, cùng với nội dung đề xuất cho nhà phát triển về cách xử lý:

Lần đầu tiên một trình chạy dịch vụ được cài đặt

Có thể bạn sẽ muốn xử lý lần đầu tiên cài đặt trình chạy dịch vụ khác với cách bạn xử lý tất cả các bản cập nhật trong tương lai.

Trong workbox-window, bạn có thể phân biệt giữa chế độ cài đặt phiên bản đầu tiên với các bản cập nhật trong tương lai bằng cách kiểm tra thuộc tính isUpdate trong những sự kiện sau đây. Trong lần cài đặt đầu tiên, isUpdate sẽ là false.

const wb = new Workbox('/sw.js');

wb.addEventListener('installed', event => {
  if (!event.isUpdate) {
    // First-installed code goes here...
  }
});

wb.register();
Sự kiện Sự kiện Hành động được đề xuất
Một trình chạy dịch vụ mới đã cài đặt (lần đầu tiên) installed

Trong lần đầu tiên cài đặt một trình chạy dịch vụ, chúng ta thường lưu trước tất cả nội dung cần thiết để trang web hoạt động khi không có mạng. Bạn có thể cân nhắc việc thông báo cho người dùng rằng trang web của họ hiện đã có thể hoạt động khi không có mạng.

Ngoài ra, vì trong lần đầu tiên một trình chạy dịch vụ cài đặt, nên dịch vụ sẽ không chặn các sự kiện tìm nạp cho lượt tải trang đó, nên bạn cũng có thể cân nhắc lưu các tài sản đã tải vào bộ nhớ đệm (mặc dù việc này không cần thiết nếu những tài sản đó đã được lưu vào bộ nhớ đệm trước). Ví dụ về gửi cho trình chạy dịch vụ danh sách các URL cần lưu vào bộ nhớ đệm ở trên cho thấy cách thực hiện việc này.

Service worker đã bắt đầu kiểm soát trang controlling

Sau khi một trình chạy dịch vụ mới được cài đặt và bắt đầu kiểm soát trang, tất cả các sự kiện tìm nạp tiếp theo sẽ chuyển qua trình chạy dịch vụ đó. Nếu trình chạy dịch vụ thêm bất kỳ logic đặc biệt nào để xử lý sự kiện tìm nạp cụ thể, thì đây là thời điểm bạn biết rằng logic sẽ chạy.

Xin lưu ý rằng trong lần đầu tiên bạn cài đặt một trình chạy dịch vụ, trình chạy dịch vụ đó sẽ không bắt đầu kiểm soát trang hiện tại trừ phi trình chạy dịch vụ đó gọi clients.claim() trong sự kiện kích hoạt. Hành vi mặc định là đợi cho đến khi trang tải tiếp theo bắt đầu kiểm soát.

Từ góc độ workbox-window, điều này có nghĩa là sự kiện controlling chỉ được gửi trong trường hợp trình chạy dịch vụ gọi clients.claim(). Sự kiện này sẽ không được gửi đi nếu trang đã được kiểm soát trước khi đăng ký.

Trình chạy dịch vụ đã kích hoạt xong activated

Như đã đề cập ở trên, lần đầu tiên một trình chạy dịch vụ hoàn tất quá trình kích hoạt có thể đã (hoặc chưa) bắt đầu kiểm soát trang.

Vì lý do này, bạn không nên theo dõi sự kiện kích hoạt để biết khi nào trình chạy dịch vụ đang kiểm soát trang. Tuy nhiên, nếu bạn đang chạy logic trong sự kiện đang hoạt động (trong trình chạy dịch vụ) và bạn cần biết khi nào logic đó hoàn tất, thì sự kiện được kích hoạt sẽ cho bạn biết điều đó.

Khi tìm thấy phiên bản cập nhật của trình chạy dịch vụ

Khi một trình chạy dịch vụ mới bắt đầu cài đặt nhưng phiên bản hiện có đang kiểm soát trang, thì thuộc tính isUpdate của tất cả các sự kiện sau đây sẽ là true.

Cách bạn phản ứng trong tình huống này thường khác với lần cài đặt đầu tiên vì bạn phải quản lý thời điểm và cách thức người dùng nhận được bản cập nhật này.

Sự kiện Sự kiện Hành động được đề xuất
Một trình chạy dịch vụ mới đã cài đặt (cập nhật phiên bản trước đó) installed

Nếu đây không phải là lần đầu tiên cài đặt trình chạy dịch vụ (event.isUpdate === true), thì điều đó có nghĩa là phiên bản mới hơn của trình chạy dịch vụ đã được tìm thấy và cài đặt (nghĩa là một phiên bản khác với phiên bản hiện đang kiểm soát trang).

Điều này thường có nghĩa là máy chủ của bạn đã triển khai phiên bản mới hơn của trang web và các tài sản mới có thể vừa hoàn tất quá trình lưu vào bộ nhớ đệm.

Lưu ý: một số nhà phát triển sử dụng sự kiện installed để thông báo cho người dùng rằng trang web của họ đã có một phiên bản mới. Tuy nhiên, tuỳ thuộc vào việc bạn có gọi skipWaiting() trong trình chạy dịch vụ đang cài đặt hay không, trình chạy dịch vụ đã cài đặt đó có thể hoạt động ngay lập tức. Nếu thực hiện gọi skipWaiting() thì bạn nên thông báo cho người dùng về bản cập nhật sau khi trình chạy dịch vụ mới được kích hoạt. Nếu không gọi skipWaiting, bạn nên thông báo cho họ về bản cập nhật đang chờ xử lý trong sự kiện đang chờ (xem bên dưới để biết thêm chi tiết).

Một trình chạy dịch vụ đã cài đặt nhưng bị kẹt trong giai đoạn chờ waiting

Nếu phiên bản cập nhật của trình chạy dịch vụ không gọi skipWaiting() khi đang được cài đặt, thì phiên bản này sẽ không được kích hoạt cho đến khi tất cả các trang do trình chạy dịch vụ đang hoạt động kiểm soát đã huỷ tải. Bạn nên thông báo cho người dùng rằng đã có bản cập nhật và sẽ áp dụng vào lần tiếp theo họ truy cập.

Cảnh báo! Các nhà phát triển thường nhắc người dùng tải lại để nhận bản cập nhật, nhưng trong nhiều trường hợp, việc làm mới trang sẽ không kích hoạt trình thực thi đã cài đặt. Nếu người dùng làm mới trang và trình chạy dịch vụ vẫn đang chờ, thì sự kiện waiting sẽ kích hoạt lại và thuộc tính event.wasWaitingBeforeRegister sẽ có giá trị đúng. Xin lưu ý rằng chúng tôi dự định cải thiện trải nghiệm này trong bản phát hành sau này. Hãy theo dõi vấn đề #1848 để biết thông tin cập nhật.

Một cách khác là nhắc người dùng và hỏi xem họ muốn tải bản cập nhật hay tiếp tục chờ. Nếu chọn nhận bản cập nhật, bạn có thể sử dụng postMessage() để yêu cầu trình chạy dịch vụ chạy skipWaiting(). Hãy xem công thức nâng cao cho phép người dùng tải lại một trang để biết ví dụ về việc này.

Service worker đã bắt đầu kiểm soát trang controlling

Khi một trình chạy dịch vụ được cập nhật bắt đầu kiểm soát trang, điều đó có nghĩa là phiên bản của trình chạy dịch vụ đang kiểm soát khác với phiên bản trình chạy dịch vụ được kiểm soát khi trang được tải. Trong một số trường hợp, điều này có thể không xảy ra, nhưng cũng có nghĩa là một số tài sản được trang hiện tại tham chiếu không còn trong bộ nhớ đệm (và cũng có thể không còn trên máy chủ). Bạn nên cân nhắc thông báo cho người dùng rằng một số phần của trang có thể không hoạt động chính xác.

Lưu ý: sự kiện controlling sẽ không kích hoạt nếu bạn không gọi skipWaiting() trong trình chạy dịch vụ.

Trình chạy dịch vụ đã kích hoạt xong activated Khi một trình chạy dịch vụ cập nhật được kích hoạt xong, điều đó có nghĩa là mọi logic bạn đang chạy trong activate của trình chạy dịch vụ đó đã hoàn tất. Nếu có bất cứ điều gì bạn cần trì hoãn cho đến khi logic đó hoàn tất, thì đây là lúc để chạy logic đó.

Khi tìm thấy phiên bản không mong muốn của trình chạy dịch vụ

Đôi khi, người dùng giữ trang web của bạn mở ở một thẻ trong nền trong một thời gian rất dài. Thậm chí, họ có thể mở một thẻ mới và chuyển đến trang web của bạn mà không biết là họ đã mở trang web của bạn trong một thẻ nền. Trong những trường hợp như vậy, có thể có hai phiên bản trang web chạy cùng lúc và điều đó có thể gây ra một số vấn đề thú vị cho nhà phát triển như bạn.

Hãy xem xét trường hợp trong đó bạn có thẻ A chạy v1 trên trang web và thẻ B chạy v2. Khi thẻ B được tải, thẻ B sẽ do phiên bản trình chạy dịch vụ vận chuyển bằng v1 kiểm soát. Tuy nhiên, trang do máy chủ trả về (nếu sử dụng chiến lược lưu vào bộ nhớ đệm ưu tiên mạng cho các yêu cầu điều hướng của bạn) sẽ chứa tất cả tài sản v2.

Tuy nhiên, đây thường không phải là vấn đề đối với thẻ B, vì khi viết mã v2, bạn đã biết mã v1 hoạt động như thế nào. Tuy nhiên, thẻ A này có thể gặp vấn đề, vì mã v1 của bạn không thể dự đoán được những thay đổi mà mã v2 có thể gây ra.

Để giúp xử lý những trường hợp này, workbox-window cũng gửi các sự kiện trong vòng đời khi phát hiện bản cập nhật từ trình chạy dịch vụ "bên ngoài", trong đó bên ngoài chỉ có nghĩa là bất kỳ phiên bản nào không phải là phiên bản mà thực thể Workbox hiện tại đã đăng ký.

Kể từ Workbox phiên bản 6 trở lên, những sự kiện này tương đương với các sự kiện đã ghi ở trên, cộng với việc thêm một thuộc tính isExternal: true được đặt trên mỗi đối tượng sự kiện. Nếu ứng dụng web của bạn cần triển khai logic cụ thể để xử lý trình chạy dịch vụ "bên ngoài", thì bạn có thể kiểm tra thuộc tính đó trong trình xử lý sự kiện.

Tránh các lỗi phổ biến

Một trong những tính năng hữu ích nhất mà Workbox cung cấp là tính năng ghi nhật ký dành cho nhà phát triển. Và điều này đặc biệt đúng với workbox-window.

Chúng tôi biết rằng việc phát triển bằng trình chạy dịch vụ thường có thể gây nhầm lẫn và khi mọi việc diễn ra trái với những gì bạn mong đợi, bạn có thể gặp khó khăn để biết lý do tại sao.

Ví dụ: khi thực hiện thay đổi đối với trình chạy dịch vụ và tải lại trang, bạn có thể không thấy thay đổi đó trong trình duyệt. Lý do có thể nhất cho việc này là trình chạy dịch vụ của bạn vẫn đang chờ kích hoạt.

Tuy nhiên, khi đăng ký một trình chạy dịch vụ với lớp Workbox, bạn sẽ nhận được thông báo về tất cả các thay đổi về trạng thái vòng đời trong bảng điều khiển dành cho nhà phát triển. Điều này sẽ giúp gỡ lỗi vì sao mọi thứ không như bạn mong đợi.

Cảnh báo trên bảng điều khiển hộp công việc dành cho nhân viên đang chờ

Ngoài ra, một lỗi phổ biến mà các nhà phát triển mắc phải khi sử dụng trình chạy dịch vụ lần đầu là đăng ký một trình chạy dịch vụ trong sai phạm vi.

Để ngăn điều này xảy ra, lớp Workbox sẽ cảnh báo bạn nếu trang đăng ký trình chạy dịch vụ không thuộc phạm vi của trình chạy dịch vụ đó. Thao tác này cũng sẽ cảnh báo bạn trong trường hợp trình chạy dịch vụ đang hoạt động nhưng chưa kiểm soát trang:

Cảnh báo trên bảng điều khiển hộp công việc (workbox-window) dành cho worker không kiểm soát

Giao tiếp qua cửa sổ với nhân viên dịch vụ

Hầu hết việc sử dụng trình chạy dịch vụ nâng cao bao gồm nhiều thông báo giữa trình chạy dịch vụ và cửa sổ. Lớp Workbox cũng giúp ích cho việc này bằng cách cung cấp một phương thức messageSW(). Phương thức này sẽ postMessage() trình chạy dịch vụ đã đăng ký của thực thể và chờ phản hồi.

Mặc dù bạn có thể gửi dữ liệu đến trình chạy dịch vụ ở bất kỳ định dạng nào, nhưng định dạng được chia sẻ bởi tất cả các gói Workbox là một đối tượng có ba thuộc tính (hai thuộc tính sau là không bắt buộc):

Tài sản Bắt buộc? Loại Nội dung mô tả
type string

Một chuỗi duy nhất, xác định thông báo này.

Theo quy ước, các loại đều được viết hoa và có dấu gạch dưới phân tách các từ. Nếu một loại biểu thị một hành động cần thực hiện, thì đó phải là một lệnh ở thì hiện tại (ví dụ: CACHE_URLS). Nếu loại biểu thị thông tin đang được báo cáo, thì loại đó phải ở thì quá khứ (ví dụ: URLS_CACHED).

meta no string Trong Workbox, đây luôn là tên của gói Workbox gửi thông báo. Khi tự gửi thông báo, bạn có thể bỏ qua thuộc tính này hoặc đặt thuộc tính này thành bất kỳ chế độ nào bạn muốn.
payload no * Dữ liệu đang được gửi. Thông thường, đây là một đối tượng, nhưng không nhất thiết phải là đối tượng đó.

Các tin nhắn được gửi qua phương thức messageSW() sẽ sử dụng MessageChannel để người nhận có thể phản hồi các tin nhắn đó. Để phản hồi một thông báo, bạn có thể gọi hàm event.ports[0].postMessage(response) trong trình nghe sự kiện thông báo. Phương thức messageSW() trả về một lời hứa sẽ giải quyết bất kỳ response nào bạn trả lời.

Dưới đây là ví dụ về cách gửi thông báo từ cửa sổ đến trình chạy dịch vụ và nhận lại phản hồi. Khối mã đầu tiên là trình nghe thông báo trong trình chạy dịch vụ, còn khối thứ hai sử dụng lớp Workbox để gửi thông báo và chờ phản hồi:

Mã trong sw.js:

const SW_VERSION = '1.0.0';

addEventListener('message', event => {
  if (event.data.type === 'GET_VERSION') {
    event.ports[0].postMessage(SW_VERSION);
  }
});

Mã trong main.js (chạy trong cửa sổ):

const wb = new Workbox('/sw.js');
wb.register();

const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);

Quản lý tính không tương thích của phiên bản

Ví dụ trên cho thấy cách bạn có thể triển khai việc kiểm tra phiên bản trình chạy dịch vụ từ cửa sổ. Ví dụ này được sử dụng vì khi gửi thông báo qua lại giữa cửa sổ và trình chạy dịch vụ, bạn cần lưu ý rằng trình chạy dịch vụ có thể không chạy cùng một phiên bản trang web mà mã trang của bạn đang chạy. Giải pháp để xử lý vấn đề này còn tuỳ thuộc vào việc bạn phân phát trang theo chế độ ưu tiên mạng hay ưu tiên bộ nhớ đệm.

Ưu tiên mạng

Khi phân phát mạng các trang của bạn trước, người dùng sẽ luôn nhận được phiên bản HTML mới nhất từ máy chủ của bạn. Tuy nhiên, lần đầu tiên người dùng truy cập lại trang web của bạn (sau khi bạn triển khai bản cập nhật), HTML họ nhận được sẽ dành cho phiên bản mới nhất, nhưng trình chạy dịch vụ chạy trong trình duyệt của họ sẽ là phiên bản được cài đặt trước đó (có thể có nhiều phiên bản đã cũ).

Bạn cần phải hiểu khả năng này vì nếu JavaScript được tải bằng phiên bản hiện tại của trang gửi thông báo đến phiên bản cũ hơn của trình chạy dịch vụ, thì phiên bản đó có thể không biết cách phản hồi (hoặc có thể phản hồi bằng định dạng không tương thích).

Do đó, bạn nên luôn lập phiên bản cho trình chạy dịch vụ và kiểm tra các phiên bản tương thích trước khi thực hiện bất kỳ công việc quan trọng nào.

Ví dụ: trong mã ở trên, nếu phiên bản trình chạy dịch vụ được lệnh gọi messageSW() trả về cũ hơn phiên bản dự kiến, bạn nên đợi cho đến khi tìm thấy bản cập nhật (điều này xảy ra khi bạn gọi register()). Tại thời điểm đó, bạn có thể thông báo cho người dùng hoặc bản cập nhật, hoặc bạn có thể bỏ qua giai đoạn chờ theo cách thủ công để kích hoạt trình chạy dịch vụ mới ngay lập tức.

Lưu vào bộ nhớ đệm trước tiên

Trái ngược với khi phân phát các trang theo chế độ ưu tiên mạng, khi phân phát các trang của bạn theo bộ nhớ đệm trước, bạn biết rằng ban đầu trang của bạn sẽ luôn là phiên bản giống với trình chạy dịch vụ (vì đó chính là phiên bản đã phân phát trang). Do đó, bạn có thể sử dụng messageSW() ngay lập tức.

Tuy nhiên, nếu phiên bản cập nhật của trình chạy dịch vụ được tìm thấy và kích hoạt khi trang của bạn gọi register() (tức là bạn cố tình bỏ qua giai đoạn chờ), thì việc gửi thông báo đến đó có thể không còn an toàn nữa.

Một chiến lược để quản lý khả năng này là sử dụng lược đồ tạo phiên bản cho phép bạn phân biệt giữa bản cập nhật có thể gây lỗi và bản cập nhật không gây ra lỗi. Đồng thời, trong trường hợp bản cập nhật có thể gây lỗi, bạn sẽ biết việc thông báo cho worker dịch vụ là không an toàn. Thay vào đó, bạn nên cảnh báo người dùng rằng họ đang chạy một phiên bản cũ của trang và đề xuất họ tải lại để nhận bản cập nhật.

Bỏ qua trình trợ giúp đang chờ

Quy ước sử dụng phổ biến khi gửi thông báo cho trình chạy cửa sổ đến dịch vụ là gửi thông báo {type: 'SKIP_WAITING'} để hướng dẫn một trình chạy dịch vụ đã được cài đặt bỏ qua giai đoạn chờ và kích hoạt.

Kể từ Workbox phiên bản 6, bạn có thể sử dụng phương thức messageSkipWaiting() để gửi thông báo {type: 'SKIP_WAITING'} đến trình chạy dịch vụ đang chờ liên kết với quá trình đăng ký trình chạy dịch vụ hiện tại. SDK sẽ tự động không làm gì nếu không có trình chạy dịch vụ đang chờ.

Loại

Workbox

Một lớp hỗ trợ xử lý việc đăng ký, cập nhật và phản ứng với các sự kiện trong vòng đời của trình chạy dịch vụ.

Thuộc tính

  • hàm khởi tạo

    void

    Tạo một thực thể Workbox mới có URL tập lệnh và các tuỳ chọn trình chạy dịch vụ. URL và các tuỳ chọn của tập lệnh cũng giống như URL và các tuỳ chọn dùng khi gọi navigation.serviceWorker.register(scriptURL, options).

    Hàm constructor sẽ có dạng như sau:

    (scriptURL: string|TrustedScriptURL,registerOptions?: object)=> {...}

    • scriptURL

      chuỗi|TrustedScriptURL

      Tập lệnh trình chạy dịch vụ liên kết với thực thể này. Hệ thống hỗ trợ việc sử dụng TrustedScriptURL.

    • registerOptions

      đối tượng không bắt buộc

  • hoạt động

    Promise<ServiceWorker>

  • đang điều khiển

    Promise<ServiceWorker>

  • getSW

    void

    Giải quyết bằng tham chiếu đến một trình chạy dịch vụ khớp với URL tập lệnh của thực thể này, ngay khi có sẵn.

    Nếu tại thời điểm đăng ký, đã có một trình chạy dịch vụ đang hoạt động hoặc đang chờ có URL tập lệnh trùng khớp, thì trình chạy đó sẽ được sử dụng (với trình chạy dịch vụ chờ được ưu tiên hơn trình chạy dịch vụ đang hoạt động nếu cả hai đều trùng khớp, vì trình chạy dịch vụ chờ đã được đăng ký gần đây hơn). Nếu không có trình chạy dịch vụ nào đang hoạt động hoặc đang chờ phù hợp tại thời điểm đăng ký, thì lời hứa sẽ không được giải quyết cho đến khi tìm thấy bản cập nhật và bắt đầu cài đặt, tại thời điểm đó, trình chạy dịch vụ cài đặt sẽ được sử dụng.

    Hàm getSW sẽ có dạng như sau:

    ()=> {...}

    • giá trị trả về

      Promise<ServiceWorker>

  • messageSW

    void

    Gửi đối tượng dữ liệu đã chuyển đến trình chạy dịch vụ do thực thể này đăng ký (thông qua workbox-window.Workbox#getSW) và phân giải bằng phản hồi (nếu có).

    Bạn có thể đặt phản hồi trong trình xử lý tin nhắn trong trình chạy dịch vụ bằng cách gọi event.ports[0].postMessage(...). Thao tác này sẽ giải quyết lời hứa do messageSW() trả về. Nếu bạn không đặt phản hồi nào, thì hứa hẹn sẽ không bao giờ được giải quyết.

    Hàm messageSW sẽ có dạng như sau:

    (data: object)=> {...}

    • data

      đối tượng

      Đối tượng cần gửi đến trình chạy dịch vụ

    • giá trị trả về

      Hứa hẹn<any>

  • messageSkipWaiting

    void

    Gửi thông báo {type: 'SKIP_WAITING'} đến trình chạy dịch vụ hiện đang ở trạng thái waiting liên kết với lượt đăng ký hiện tại.

    Nếu không có đăng ký hiện tại hoặc không có trình chạy dịch vụ nào là waiting, thì việc gọi lệnh này sẽ không có hiệu lực.

    Hàm messageSkipWaiting sẽ có dạng như sau:

    ()=> {...}

  • register

    void

    Đăng ký một trình chạy dịch vụ cho các phiên bản URL tập lệnh và các tuỳ chọn của trình chạy dịch vụ. Theo mặc định, phương thức này trì hoãn việc đăng ký cho đến khi cửa sổ tải xong.

    Hàm register sẽ có dạng như sau:

    (options?: object)=> {...}

    • tùy chọn

      đối tượng không bắt buộc

      • sát cạnh

        boolean không bắt buộc

    • giá trị trả về

      Promise<ServiceWorkerRegistration>

  • cập nhật

    void

    Kiểm tra bản cập nhật của trình chạy dịch vụ đã đăng ký.

    Hàm update sẽ có dạng như sau:

    ()=> {...}

    • giá trị trả về

      Promise<void>

WorkboxEventMap

Thuộc tính

WorkboxLifecycleEvent

Thuộc tính

  • isExternal

    boolean không bắt buộc

  • isUpdate

    boolean không bắt buộc

  • originalEvent

    Sự kiện không bắt buộc

  • sw

    ServiceWorker không bắt buộc

  • mục tiêu

    WorkboxEventTarget không bắt buộc

  • loại

    typeOperator

WorkboxLifecycleEventMap

Thuộc tính

WorkboxLifecycleWaitingEvent

Thuộc tính

  • isExternal

    boolean không bắt buộc

  • isUpdate

    boolean không bắt buộc

  • originalEvent

    Sự kiện không bắt buộc

  • sw

    ServiceWorker không bắt buộc

  • mục tiêu

    WorkboxEventTarget không bắt buộc

  • loại

    typeOperator

  • wasWaitingBeforeRegister

    boolean không bắt buộc

WorkboxMessageEvent

Thuộc tính

  • data

    Bất kỳ

  • isExternal

    boolean không bắt buộc

  • originalEvent

    Sự kiện

  • ports

    typeOperator

  • sw

    ServiceWorker không bắt buộc

  • mục tiêu

    WorkboxEventTarget không bắt buộc

  • loại

Phương thức

messageSW()

workbox-window.messageSW(
  sw: ServiceWorker,
  data: object,
)

Gửi một đối tượng dữ liệu đến một trình chạy dịch vụ qua postMessage và phân giải bằng phản hồi (nếu có).

Bạn có thể đặt phản hồi trong trình xử lý tin nhắn trong trình chạy dịch vụ bằng cách gọi event.ports[0].postMessage(...). Thao tác này sẽ giải quyết lời hứa do messageSW() trả về. Nếu bạn không đặt phản hồi nào, hứa hẹn sẽ không được giải quyết.

Tham số

  • sw

    ServiceWorker

    Trình chạy dịch vụ để gửi thông báo đến.

  • data

    đối tượng

    Một đối tượng để gửi đến trình chạy dịch vụ.

Giá trị trả về

  • Hứa hẹn<any>