Di chuyển từ Workbox phiên bản 4 sang phiên bản 5

Hướng dẫn này tập trung vào những thay đổi có thể gây lỗi được giới thiệu trong Workbox v5, kèm theo ví dụ về những thay đổi bạn cần thực hiện khi nâng cấp từ Workbox v4.

Thay đổi có thể gây lỗi

Đã đổi tên lớp trình bổ trợ

Một số gói Workbox v4 bao gồm các lớp có tên là Plugin. Trong phiên bản 5, các lớp đó đã được đổi tên để tuân theo giá trị nhận dạng gói mẫu + Plugin:

  • BackgroundSyncPlugin
  • BroadcastUpdatePlugin
  • CacheableResponsePlugin
  • ExpirationPlugin
  • RangeRequestsPlugin

Việc đổi tên này sẽ áp dụng cho dù bạn dùng các lớp thông qua tính năng nhập mô-đun hay thông qua không gian tên workbox.*.

Điểm thay thế tệp kê khai bộ nhớ đệm mặc định

Trước đây, khi bạn sử dụng một trong các công cụ xây dựng ở chế độ "chèn tệp kê khai", tệp trình chạy dịch vụ nguồn của bạn đã được kiểm tra sự hiện diện của precacheAndRoute([]), với mảng trống [] được dùng làm phần giữ chỗ cho thời điểm mà tệp kê khai bộ nhớ đệm được chèn vào.

Trong Workbox phiên bản 5, logic thay thế đã thay đổi và giờ đây, self.__WB_MANIFEST được dùng làm điểm chèn theo mặc định.

// v4:
precacheAndRoute([]);

// v5:
precacheAndRoute(self.__WB_MANIFEST);

Như đã trình bày trong thảo luận này, chúng tôi tin rằng thay đổi này mang đến trải nghiệm đơn giản hơn, đồng thời mang lại cho nhà phát triển nhiều quyền kiểm soát hơn đối với cách dùng tệp kê khai được chèn trong mã trình chạy dịch vụ tuỳ chỉnh. Nếu cần, bạn có thể thay đổi chuỗi thay thế này thông qua tuỳ chọn cấu hình injectionPoint.

2 tuỳ chọn từng được hỗ trợ cho các tuyến điều hướng (blacklistwhitelist) đã được đổi tên thành denylistallowlist.

Trước đây, workbox-routing đã hỗ trợ một phương thức registerNavigationRoute(), nâng cao đã thực hiện hai việc:

  1. Đã phát hiện xem một sự kiện fetch nhất định có mode'navigate' hay không.
  2. Nếu có, hãy phản hồi yêu cầu đó bằng cách sử dụng nội dung của một URL được mã hoá cứng được lưu vào bộ nhớ đệm trước đó, bất kể URL đó đang được điều hướng đến.

Đây là mẫu phổ biến được sử dụng khi triển khai cấu trúc App Shell.

Bước thứ hai, tạo phản hồi bằng cách đọc từ bộ nhớ đệm, nằm ngoài trách nhiệm của workbox-routing. Thay vào đó, chúng ta thấy đây là chức năng phải thuộc workbox-precaching thông qua một phương thức mới là createHandlerBoundToURL(). Phương thức mới này có thể hoạt động cùng với lớp NavigationRoute hiện có trong workbox-routing để thực hiện logic tương tự.

Nếu bạn đang dùng tuỳ chọn navigateFallback ở một trong các chế độ "tạo SW" của công cụ xây dựng, thì quá trình chuyển đổi sẽ tự động diễn ra. Nếu trước đó bạn đã định cấu hình các tuỳ chọn navigateFallbackBlacklist hoặc navigateFallbackWhitelist, hãy thay đổi các tuỳ chọn đó thành navigateFallbackDenylist hoặc navigateFallbackAllowlist tương ứng.

Nếu bạn đang sử dụng chế độ "chèn tệp kê khai" hoặc chỉ tự viết trình chạy dịch vụ và trình chạy dịch vụ Workbox phiên bản 4 của bạn gọi trực tiếp registerNavigationRoute(), thì bạn sẽ phải thay đổi mã để nhận được hành vi tương đương.

// v4:
import {getCacheKeyForURL} from 'workbox-precaching';
import {registerNavigationRoute} from 'workbox-routing';

const appShellCacheKey = getCacheKeyForURL('/app-shell.html');
registerNavigationRoute(appShellCacheKey, {
  whitelist: [...],
  blacklist: [...],
});

// v5:
import {createHandlerBoundToURL} from 'workbox-precaching';
import {NavigationRoute, registerRoute} from 'workbox-routing';

const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler, {
  allowlist: [...],
  denylist: [...],
});
registerRoute(navigationRoute);

Bạn không cần gọi getCacheKeyForURL() nữa, vì createHandlerBoundToURL() sẽ xử lý việc đó cho bạn.

Xoá makeRequest() khỏi workbox-chiến lược

Việc gọi makeRequest() hầu như tương đương với việc gọi handle() trên một trong các lớp workbox-strategy. Sự khác biệt giữa hai phương pháp rất nhỏ nên việc duy trì cả hai phương pháp là không hợp lý. Các nhà phát triển đã gọi makeRequest() có thể chuyển sang sử dụng handle() mà không cần thay đổi thêm:

// v4:
const strategy = new StaleWhileRevalidate({...});
const response = await strategy.makeRequest({event, request});

// v5:
const strategy = new StaleWhileRevalidate({...});
const response = await strategy.handle({event, request});

Trong phiên bản 5, handle() sẽ coi request là một tham số bắt buộc và sẽ không quay lại sử dụng event.request. Đảm bảo bạn truyền yêu cầu hợp lệ khi gọi handle().

Workbox-broadcast-update Luôn sử dụng postMessage()

Trong phiên bản 4, theo mặc định, thư viện workbox-broadcast-update sẽ sử dụng broadcast Channel API (API kênh phát sóng) để gửi thông báo khi thư viện này được hỗ trợ và chỉ quay lại sử dụng postMessage() khi không hỗ trợ Kênh truyền phát.

Chúng tôi nhận ra rằng việc phải theo dõi hai nguồn thư đến tiềm năng khiến việc viết mã phía máy khách trở nên quá phức tạp. Ngoài ra, trên một số trình duyệt, các lệnh gọi postMessage() từ trình chạy dịch vụ được gửi đến các trang ứng dụng sẽ tự động được lưu vào vùng đệm cho đến khi trình nghe sự kiện message được thiết lập. Broadcast Channel API không tải vào bộ đệm và thông báo được phát đi sẽ chỉ bị huỷ nếu được gửi trước khi trang khách sẵn sàng nhận chúng.

Vì những lý do đó, chúng tôi đã thay đổi workbox-broadcast-update để luôn sử dụng postMessage() trong phiên bản 5. Tin nhắn được gửi lần lượt đến tất cả các trang ứng dụng trong phạm vi của trình chạy dịch vụ hiện tại.

Để thích ứng với hành vi mới này, bạn có thể xoá bất kỳ mã nào bạn có trong những trang ứng dụng đã tạo bản sao BroadcastChannel và thay vào đó, thiết lập trình nghe sự kiện message trên navigator.serviceWorker:

// v4:
const updatesChannel = new BroadcastChannel('api-updates');
updatesChannel.addEventListener('message', event => {
  const {cacheName, updatedUrl} = event.data.payload;
  // ... your code here ...
});

// v5:
// This listener should be added as early as possible in your page's lifespan
// to ensure that messages are properly buffered.
navigator.serviceWorker.addEventListener('message', event => {
  // Optional: ensure the message came from workbox-broadcast-update
  if (event.meta === 'workbox-broadcast-update') {
    const {cacheName, updatedUrl} = event.data.payload;
    // ... your code here ...
  }
});

Người dùng workbox-window sẽ không cần thực hiện bất kỳ thay đổi nào vì logic nội bộ của hàm này đã được cập nhật để theo dõi các lệnh gọi postMessage().

Công cụ xây dựng yêu cầu Node.js v8 trở lên

Các phiên bản Node.js trước phiên bản 8 không còn được hỗ trợ cho workbox-webpack-plugin, workbox-build hoặc workbox-cli. Nếu bạn đang chạy phiên bản Node.js trước phiên bản 8, hãy cập nhật thời gian chạy lên một phiên bản được hỗ trợ.

workbox-webpack-plugin cần có webpack phiên bản 4 trở lên

Nếu bạn đang dùng workbox-webpack-plugin, hãy cập nhật chế độ thiết lập gói web để sử dụng ít nhất gói web phiên bản 4.

Kiểm tra toàn bộ tuỳ chọn công cụ xây dựng

Một số tham số cấu hình workbox-build, workbox-cliworkbox-webpack-plugin không còn được hỗ trợ nữa. Ví dụ: generateSW sẽ luôn tạo một gói thời gian chạy Workbox cục bộ cho bạn, vì vậy, tuỳ chọn importWorkboxFrom sẽ không còn hợp lý nữa.

Hãy tham khảo tài liệu của công cụ liên quan để biết danh sách các tuỳ chọn được hỗ trợ.

Xoá generateSWString khỏi bản dựng hộp công việc

Chế độ generateSWString đã bị xoá khỏi workbox-build. Chúng tôi dự kiến việc này sẽ gây ảnh hưởng rất nhỏ, vì tính năng này chủ yếu được workbox-webpack-plugin sử dụng nội bộ.

Các thay đổi không bắt buộc

Sử dụng tính năng nhập mô-đun

Mặc dù thay đổi này là a) không bắt buộc và b) về mặt kỹ thuật là có thể thực hiện khi sử dụng Workbox v4, nhưng thay đổi lớn nhất mà chúng tôi dự đoán khi chuyển sang v5 là mô hình trong đó bạn tạo trình chạy dịch vụ đi kèm của riêng mình bằng cách nhập các mô-đun của Workbox. Đây là một phương pháp thay thế cho việc gọi importScripts('/path/to/workbox-sw.js') ở đầu trình chạy dịch vụ và sử dụng Workbox qua không gian tên workbox.*.

Nếu bạn đang sử dụng một trong các công cụ xây dựng (workbox-webpack-plugin, workbox-build, workbox-cli) ở chế độ "tạo SW", thì thay đổi này sẽ tự động xảy ra cho bạn. Tất cả các công cụ đó sẽ tạo ra một gói thời gian chạy Workbox cục bộ, tuỳ chỉnh cùng với mã thực tế cần thiết để triển khai logic của trình chạy dịch vụ. Trong trường hợp này, không còn bất kỳ phần phụ thuộc nào trên workbox-sw hoặc bản sao CDN của Workbox. Tuỳ thuộc vào giá trị cấu hình inlineWorkboxRuntime, môi trường thời gian chạy Workbox sẽ được chia thành một tệp riêng để triển khai cùng với trình chạy dịch vụ của bạn (khi được đặt thành false, giá trị mặc định) hoặc được đưa vào cùng dòng với logic của trình chạy dịch vụ (khi đặt thành true).

Nếu đang sử dụng công cụ bản dựng ở chế độ "chèn tệp kê khai" hoặc không sử dụng công cụ xây dựng của Workbox, bạn có thể tìm hiểu thêm về cách tạo gói thời gian chạy Workbox của riêng mình trong hướng dẫn Sử dụng gói (webpack/Rollup) với Workbox hiện có.

Tài liệu và ví dụ cho v5 được viết với giả định cú pháp nhập mô-đun, mặc dù không gian tên workbox.* sẽ tiếp tục được hỗ trợ trong Workbox v5.

Đọc câu trả lời được lưu trước trong bộ nhớ đệm

Một số nhà phát triển cần đọc trực tiếp các phản hồi được lưu trước vào bộ nhớ đệm từ bộ nhớ đệm, thay vì ngầm sử dụng các phản hồi đó thông qua phương thức precacheAndRoute(). Một cách làm phổ biến trong phiên bản 4 là lấy khoá bộ nhớ đệm dành riêng cho phiên bản hiện tại của tài nguyên được lưu trước vào bộ nhớ đệm, sau đó truyền khoá đó cùng với tên bộ nhớ đệm của bộ nhớ đệm trước vào caches.match() để lấy Response.

Để đơn giản hoá quá trình này, workbox-precaching trong phiên bản 5 hỗ trợ một phương thức mới tương đương là matchPrecache():

// v4:
import {cacheNames} from 'workbox-core';
import {getCacheKeyForURL} from 'workbox-precaching';

const cachedResponse = await caches.match(
  getCacheKeyForURL(`/somethingPrecached`),
  {
    cacheName: cacheNames.precache,
  }
);

// v5:
import {matchPrecache} from 'workbox-precaching';

const cachedResponse = await matchPrecache(`/somethingPrecached`);

Sử dụng TypeScript

Trong phiên bản 5, thư viện thời gian chạy Workbox được viết bằng TypeScript. Mặc dù chúng tôi sẽ tiếp tục xuất bản các gói và mô-đun JavaScript đã chuyển mã để hỗ trợ những nhà phát triển chưa sử dụng TypeScript, nhưng nếu đang sử dụng TypeScript, bạn sẽ được hưởng lợi từ thông tin loại chính xác và luôn cập nhật trực tiếp từ dự án Workbox.

Ví dụ về việc di chuyển

Cam kết này minh hoạ một quá trình di chuyển khá phức tạp, kèm theo bình luận cùng dòng. Phương thức này sử dụng Rollup để đưa thời gian chạy Workbox tuỳ chỉnh vào trình chạy dịch vụ cuối cùng thay vì tải thời gian chạy từ CDN.

Mặc dù không bao gồm mọi thay đổi có thể gây lỗi, nhưng dưới đây là danh sách trướcsau khi nâng cấp một tệp trình chạy dịch vụ từ phiên bản 4 lên phiên bản 5, bao gồm cả việc chuyển sang TypeScript.

Nhận trợ giúp

Chúng tôi dự kiến rằng hầu hết quá trình di chuyển sẽ đơn giản. Nếu bạn gặp phải các vấn đề không có trong hướng dẫn này, hãy cho chúng tôi biết bằng cách mở vấn đề trên GitHub.