Sử dụng plugin

Khi sử dụng Workbox, bạn có thể muốn thao tác với một yêu cầu và phản hồi khi yêu cầu đó đang được tìm nạp hoặc lưu vào bộ nhớ đệm. Trình bổ trợ Workbox cho phép bạn thêm các hành vi bổ sung vào worker dịch vụ với mã nguyên mẫu tối thiểu. Những bản ghi âm này có thể được đóng gói lại và sử dụng lại trong dự án của bạn hoặc phát hành công khai để người khác sử dụng.

Workbox cung cấp một số trình bổ trợ sẵn có cho chúng ta và nếu là người khéo léo, bạn có thể viết trình bổ trợ tuỳ chỉnh phù hợp với yêu cầu của ứng dụng.

Các trình bổ trợ Workbox hiện có

Workbox cung cấp các trình bổ trợ chính thức sau đây để sử dụng trong worker dịch vụ:

Trình bổ trợ Workbox (dù là một trong các trình bổ trợ được liệt kê ở trên hay một trình bổ trợ tuỳ chỉnh) được sử dụng với chiến lược Workbox bằng cách thêm một thực thể của trình bổ trợ vào thuộc tính plugins của chiến lược:

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'images',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
      }),
    ],
  })
);

Phương thức cho trình bổ trợ tuỳ chỉnh

Trình bổ trợ Workbox cần triển khai một hoặc nhiều hàm gọi lại. Khi bạn thêm một trình bổ trợ vào Chiến lược, các hàm callback sẽ tự động chạy vào đúng thời điểm. Chiến lược sẽ truyền hàm gọi lại thông tin liên quan về yêu cầu và/hoặc phản hồi hiện tại, cung cấp cho trình bổ trợ ngữ cảnh cần thiết để thực hiện hành động. Các hàm gọi lại sau đây được hỗ trợ:

  • cacheWillUpdate: Được gọi trước khi Response được dùng để cập nhật bộ nhớ đệm. Trong phương thức này, bạn có thể thay đổi phản hồi trước khi thêm phản hồi vào bộ nhớ đệm hoặc bạn có thể trả về null để tránh cập nhật toàn bộ bộ nhớ đệm.
  • cacheDidUpdate: Được gọi khi một mục mới được thêm vào bộ nhớ đệm hoặc nếu một mục hiện có được cập nhật. Các trình bổ trợ sử dụng phương thức này có thể hữu ích khi bạn muốn thực hiện một hành động sau khi cập nhật bộ nhớ đệm.
  • cacheKeyWillBeUsed: Được gọi trước khi một yêu cầu được dùng làm khoá bộ nhớ đệm. Điều này xảy ra đối với cả các lượt tra cứu bộ nhớ đệm (khi mode'read') và các lượt ghi bộ nhớ đệm (khi mode'write'). Lệnh gọi lại này rất hữu ích nếu bạn cần ghi đè hoặc chuẩn hoá URL trước khi sử dụng URL để truy cập vào bộ nhớ đệm.
  • cachedResponseWillBeUsed: Hàm này được gọi ngay trước khi một phản hồi từ bộ nhớ đệm được sử dụng để bạn có thể kiểm tra phản hồi đó. Tại thời điểm này, bạn có thể trả về một phản hồi khác hoặc trả về null.
  • requestWillFetch: Được gọi bất cứ khi nào có yêu cầu sắp được truyền đến mạng. Hữu ích khi bạn cần thay đổi Request ngay trước khi gửi đến mạng.
  • fetchDidFail: Được gọi khi một yêu cầu mạng không thành công, rất có thể là do không có kết nối mạng và sẽ không kích hoạt khi trình duyệt có kết nối mạng nhưng nhận được lỗi (ví dụ: 404 Not Found).
  • fetchDidSucceed: Được gọi bất cứ khi nào một yêu cầu mạng thành công, bất kể mã phản hồi HTTP.
  • handlerWillStart: Được gọi trước khi bất kỳ logic trình xử lý nào bắt đầu chạy. Điều này sẽ hữu ích nếu bạn cần đặt trạng thái trình xử lý ban đầu. Ví dụ: nếu muốn biết trình xử lý mất bao lâu để tạo phản hồi, bạn có thể ghi lại thời gian bắt đầu trong lệnh gọi lại này.
  • handlerWillRespond: Được gọi trước khi phương thức handle() của chiến lược trả về một phản hồi. Điều này sẽ hữu ích nếu bạn cần sửa đổi phản hồi trước khi trả về phản hồi đó cho RouteHandler hoặc logic tuỳ chỉnh khác.
  • handlerDidRespond: Được gọi sau khi phương thức handle() của chiến lược trả về một phản hồi. Đây là lúc bạn nên ghi lại mọi thông tin chi tiết về phản hồi cuối cùng (ví dụ: sau khi các trình bổ trợ khác thực hiện thay đổi).
  • handlerDidComplete: Được gọi sau khi tất cả lời hứa kéo dài thời gian hoạt động được thêm vào sự kiện từ lệnh gọi của chiến lược đã được giải quyết. Điều này rất hữu ích nếu bạn cần báo cáo về bất kỳ dữ liệu nào cần chờ cho đến khi trình xử lý hoàn tất để tính toán các thông tin như trạng thái truy cập bộ nhớ đệm, độ trễ bộ nhớ đệm, độ trễ mạng và các thông tin hữu ích khác.
  • handlerDidError: Được gọi nếu trình xử lý không thể cung cấp phản hồi hợp lệ từ bất kỳ nguồn nào. Đây là thời điểm tối ưu để cung cấp một số loại phản hồi dự phòng thay vì hoàn toàn không phản hồi.

Tất cả các lệnh gọi lại này đều là async, do đó, bạn sẽ phải sử dụng await bất cứ khi nào sự kiện bộ nhớ đệm hoặc tìm nạp đạt đến điểm liên quan cho lệnh gọi lại có liên quan.

Nếu một trình bổ trợ sử dụng tất cả các lệnh gọi lại ở trên, thì đây sẽ là mã kết quả:

const myPlugin = {
  cacheWillUpdate: async ({request, response, event, state}) => {
    // Return `response`, a different `Response` object, or `null`.
    return response;
  },
  cacheDidUpdate: async ({
    cacheName,
    request,
    oldResponse,
    newResponse,
    event,
    state,
  }) => {
    // No return expected
    // Note: `newResponse.bodyUsed` is `true` when this is called,
    // meaning the body has already been read. If you need access to
    // the body of the fresh response, use a technique like:
    // const freshResponse = await caches.match(request, {cacheName});
  },
  cacheKeyWillBeUsed: async ({request, mode, params, event, state}) => {
    // `request` is the `Request` object that would otherwise be used as the cache key.
    // `mode` is either 'read' or 'write'.
    // Return either a string, or a `Request` whose `url` property will be used as the cache key.
    // Returning the original `request` will make this a no-op.
    return request;
  },
  cachedResponseWillBeUsed: async ({
    cacheName,
    request,
    matchOptions,
    cachedResponse,
    event,
    state,
  }) => {
    // Return `cachedResponse`, a different `Response` object, or null.
    return cachedResponse;
  },
  requestWillFetch: async ({request, event, state}) => {
    // Return `request` or a different `Request` object.
    return request;
  },
  fetchDidFail: async ({originalRequest, request, error, event, state}) => {
    // No return expected.
    // Note: `originalRequest` is the browser's request, `request` is the
    // request after being passed through plugins with
    // `requestWillFetch` callbacks, and `error` is the exception that caused
    // the underlying `fetch()` to fail.
  },
  fetchDidSucceed: async ({request, response, event, state}) => {
    // Return `response` to use the network response as-is,
    // or alternatively create and return a new `Response` object.
    return response;
  },
  handlerWillStart: async ({request, event, state}) => {
    // No return expected.
    // Can set initial handler state here.
  },
  handlerWillRespond: async ({request, response, event, state}) => {
    // Return `response` or a different `Response` object.
    return response;
  },
  handlerDidRespond: async ({request, response, event, state}) => {
    // No return expected.
    // Can record final response details here.
  },
  handlerDidComplete: async ({request, response, error, event, state}) => {
    // No return expected.
    // Can report any data here.
  },
  handlerDidError: async ({request, event, error, state}) => {
    // Return a `Response` to use as a fallback, or `null`.
    return fallbackResponse;
  },
};

Đối tượng event có trong các lệnh gọi lại được liệt kê ở trên là sự kiện ban đầu đã kích hoạt thao tác tìm nạp hoặc lưu vào bộ nhớ đệm. Đôi khi, sẽ không phải là sự kiện gốc. Vì vậy, mã của bạn phải kiểm tra xem sự kiện đó có tồn tại hay không trước khi tham chiếu đến.

Tất cả lệnh gọi lại trình bổ trợ cũng được truyền một đối tượng state, đối tượng này dành riêng cho một trình bổ trợ cụ thể và chiến lược mà trình bổ trợ đó gọi. Điều này có nghĩa là bạn có thể viết các trình bổ trợ trong đó một lệnh gọi lại có thể thực hiện một tác vụ có điều kiện dựa trên nội dung mà một lệnh gọi lại khác trong cùng một trình bổ trợ đã thực hiện (ví dụ: tính toán sự khác biệt giữa việc chạy requestWillFetch()fetchDidSucceed() hoặc fetchDidFail()).

Trình bổ trợ của bên thứ ba

Nếu phát triển một trình bổ trợ và cho rằng trình bổ trợ đó có thể sử dụng bên ngoài dự án, bạn nên phát hành trình bổ trợ đó dưới dạng mô-đun! Dưới đây là danh sách ngắn về các trình bổ trợ Workbox do cộng đồng cung cấp:

Bạn có thể tìm thêm các trình bổ trợ Workbox do cộng đồng cung cấp bằng cách tìm kiếm trong kho lưu trữ của npm.

Cuối cùng, nếu bạn đã tạo một trình bổ trợ Workbox mà bạn muốn chia sẻ, hãy thêm từ khoá workbox-plugin khi bạn phát hành trình bổ trợ đó. Nếu có, hãy cho chúng tôi biết trên Twitter @WorkboxJS!