định tuyến hộp công việc

Trình chạy dịch vụ có thể chặn các yêu cầu mạng cho một trang. Trợ lý có thể phản hồi với trình duyệt có nội dung được lưu vào bộ nhớ đệm, nội dung từ mạng hoặc nội dung được tạo trong trình chạy dịch vụ.

workbox-routing là một mô-đun giúp bạn dễ dàng "định tuyến" những yêu cầu này đến các hàm khác nhau cung cấp phản hồi.

Cách thực hiện việc định tuyến

Khi một yêu cầu mạng gây ra sự kiện tìm nạp trình chạy dịch vụ, workbox-routing sẽ cố gắng phản hồi yêu cầu bằng các tuyến và trình xử lý được cung cấp.

Sơ đồ định tuyến hộp làm việc

Những điều chính cần lưu ý ở trên là:

  • Phương thức của yêu cầu là một yếu tố quan trọng. Theo mặc định, Tuyến đường được đăng ký cho GET yêu cầu. Nếu muốn chặn các loại yêu cầu khác, bạn cần để chỉ định phương thức.

  • Thứ tự đăng ký Tuyến đường là rất quan trọng. Nếu có nhiều Tuyến đường đã đăng ký có thể xử lý yêu cầu, Tuyến được đăng ký trước sẽ được dùng để phản hồi yêu cầu.

Có một số cách để đăng ký một tuyến: bạn có thể sử dụng các lệnh gọi lại, biểu thức hoặc bản sao Tuyến đường.

So khớp và xử lý trong tuyến đường

Một "tuyến đường" trong hộp công việc chỉ là hai chức năng: "phù hợp" hàm để xác định xem tuyến đường có phù hợp với yêu cầu và "xử lý" không hàm, sẽ xử lý yêu cầu và phản hồi bằng một phản hồi.

Workbox đi kèm với một số trình trợ giúp sẽ thực hiện việc so khớp và xử lý bạn, nhưng nếu bạn muốn có một hành vi khác, hãy viết kết hợp tuỳ chỉnh và chức năng trình xử lý là lựa chọn tốt nhất.

Đáp khớp hàm callback được truyền một ExtendableEvent! Request và một URL đối tượng bạn có thể bằng cách trả về một giá trị trung thực. Ví dụ đơn giản: bạn có thể so khớp với một URL cụ thể, chẳng hạn như:

const matchCb = ({url, request, event}) => {
  return url.pathname === '/special/url';
};

Hầu hết các trường hợp sử dụng đều có thể được kiểm tra bằng cách kiểm tra / kiểm thử url hoặc request

Đáp hàm callback xử lý sẽ được cấp cùng một ExtendableEvent! RequestURL đối tượng cùng với giá trị params, là giá trị được lệnh "khớp" trả về .

const handlerCb = async ({url, request, event, params}) => {
  const response = await fetch(request);
  const responseBody = await response.text();
  return new Response(`${responseBody} <!-- Look Ma. Added Content. -->`, {
    headers: response.headers,
  });
};

Trình xử lý của bạn phải trả về một lời hứa phân giải thành Response. Trong phần này Ví dụ: chúng tôi đang sử dụng asyncawait. Về sau, giá trị Response trả về sẽ được gói gọn trong một lời hứa.

Bạn có thể đăng ký các lệnh gọi lại này như sau:

import {registerRoute} from 'workbox-routing';

registerRoute(matchCb, handlerCb);

Hạn chế duy nhất là "sự trùng khớp" lệnh gọi lại phải đồng bộ trả về giá trị trung thực , bạn không thể thực hiện bất kỳ công việc không đồng bộ nào. Lý do là Router phải phản hồi một cách đồng bộ với sự kiện tìm nạp hoặc cho phép rơi đến các sự kiện tìm nạp khác.

Thường là "handler" lệnh gọi lại sẽ sử dụng một trong các chiến lược được cung cấp theo workbox-strategy như sau:

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

registerRoute(matchCb, new StaleWhileRevalidate());

Trong trang này, chúng tôi sẽ tập trung vào workbox-routing nhưng bạn có thể tìm hiểu thêm về các chiến lược này đối với các chiến lược hộp công việc.

Cách đăng ký tuyến biểu thức chính quy

Phương pháp phổ biến là sử dụng biểu thức chính quy thay vì "so khớp" . Workbox giúp bạn dễ dàng triển khai như sau:

import {registerRoute} from 'workbox-routing';

registerRoute(new RegExp('/styles/.*\\.css'), handlerCb);

Đối với các yêu cầu từ cùng nguồn gốc, biểu thức chính quy này sẽ khớp miễn là URL của yêu cầu khớp với biểu thức chính quy.

  • https://example.com/styles/main.css
  • https://example.com/styles/nested/file.css
  • https://example.com/nested/styles/directory.css

Tuy nhiên, đối với các yêu cầu trên nhiều nguồn gốc, biểu thức chính quy phải khớp với phần đầu của URL. Lý do là vì không chắc chắn rằng với biểu thức chính quy new RegExp('/styles/.*\\.css') mà bạn dự định so khớp với các tệp CSS của bên thứ ba.

  • https://cdn.third-party-site.com/styles/main.css
  • https://cdn.third-party-site.com/styles/nested/file.css
  • https://cdn.third-party-site.com/nested/styles/directory.css

Nếu muốn hành vi này, bạn chỉ cần đảm bảo rằng quy tắc khớp với phần đầu của URL. Nếu chúng tôi muốn phù hợp với cho https://cdn.third-party-site.com, chúng ta có thể sử dụng toán tử thông thường biểu thức new RegExp('https://cdn\\.third-party-site\\.com.*/styles/.*\\.css').

  • https://cdn.third-party-site.com/styles/main.css
  • https://cdn.third-party-site.com/styles/nested/file.css
  • https://cdn.third-party-site.com/nested/styles/directory.css

Nếu muốn so khớp với cả bên địa phương và bên thứ ba, bạn có thể sử dụng ký tự đại diện ở đầu biểu thức chính quy, nhưng bạn nên thận trọng khi thực hiện thao tác này để đảm bảo không gây ra hành vi không mong muốn trong ứng dụng web của bạn.

Cách đăng ký tuyến đường điều hướng

Nếu trang web của bạn là ứng dụng trang đơn, bạn có thể sử dụng NavigationRoute đến trả về một phản hồi cụ thể cho tất cả yêu cầu chỉ đường.

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

// This assumes /app-shell.html has been precached.
const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler);
registerRoute(navigationRoute);

Bất cứ khi nào người dùng truy cập vào trang web của bạn trong trình duyệt, yêu cầu cho trang đó sẽ là yêu cầu điều hướng và nó sẽ được phân phát trang được lưu vào bộ nhớ đệm /app-shell.html. (Lưu ý: Bạn nên lưu trang vào bộ nhớ đệm qua workbox-precaching hoặc qua bước cài đặt riêng).

Theo mặc định, lệnh này sẽ phản hồi tất cả các yêu cầu điều hướng. Nếu bạn muốn để hạn chế lệnh đó phản hồi một nhóm nhỏ URL, bạn có thể sử dụng allowlistdenylist để hạn chế những trang nào sẽ khớp với tuyến này.

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

// This assumes /app-shell.html has been precached.
const handler = createHandlerBoundToURL('/app-shell.html');
const navigationRoute = new NavigationRoute(handler, {
  allowlist: [new RegExp('/blog/')],
  denylist: [new RegExp('/blog/restricted/')],
});
registerRoute(navigationRoute);

Điều duy nhất cần lưu ý là denylist sẽ giành chiến thắng nếu một URL nằm trong cả hai allowlistdenylist.

Đặt trình xử lý mặc định

Nếu bạn muốn cung cấp "xử lý" cho các yêu cầu không khớp với một tuyến đường, bạn có thể đặt trình xử lý mặc định.

import {setDefaultHandler} from 'workbox-routing';

setDefaultHandler(({url, event, params}) => {
  // ...
});

Đặt trình xử lý bắt

Trong trường hợp bất kỳ tuyến đường nào của bạn bị lỗi, bạn có thể ghi lại và hãy xuống cấp nhẹ bằng cách thiết lập trình xử lý bắt.

import {setCatchHandler} from 'workbox-routing';

setCatchHandler(({url, event, params}) => {
  ...
});

Xác định tuyến cho các yêu cầu không phải GET

Theo mặc định, tất cả các tuyến đều dành cho các yêu cầu GET.

Nếu muốn định tuyến các yêu cầu khác, chẳng hạn như yêu cầu POST, bạn cần để xác định phương thức khi đăng ký tuyến, như sau:

import {registerRoute} from 'workbox-routing';

registerRoute(matchCb, handlerCb, 'POST');
registerRoute(new RegExp('/api/.*\\.json'), handlerCb, 'POST');

Ghi nhật ký bộ định tuyến

Bạn phải xác định được luồng yêu cầu bằng cách sử dụng nhật ký từ workbox-routing sẽ đánh dấu những URL đang được xử lý thông qua Workbox.

Nhật ký định tuyến

Nếu cần thông tin chi tiết hơn, bạn có thể đặt cấp độ nhật ký thành debug thành xem nhật ký trên các yêu cầu không được Bộ định tuyến xử lý. Xem hướng dẫn gỡ lỗi để biết thêm thông tin về đặt cấp độ nhật ký.

Thông báo định tuyến gỡ lỗi và ghi nhật ký

Cách sử dụng nâng cao

Nếu bạn muốn có nhiều quyền kiểm soát hơn đối với thời điểm Bộ định tuyến hộp làm việc được cung cấp các yêu cầu của riêng mình, bạn có thể tạo Thực thể và lệnh gọi Router thời điểm hiện tại là handleRequest() bất cứ khi nào bạn muốn sử dụng bộ định tuyến để phản hồi một yêu cầu.

import {Router} from 'workbox-routing';

const router = new Router();

self.addEventListener('fetch', event => {
  const {request} = event;
  const responsePromise = router.handleRequest({
    event,
    request,
  });
  if (responsePromise) {
    // Router found a route to handle the request.
    event.respondWith(responsePromise);
  } else {
    // No route was found to handle the request.
  }
});

Khi sử dụng trực tiếp Router, bạn cũng cần dùng lớp Route, hoặc bất kỳ lớp mở rộng nào để đăng ký tuyến.

import {Route, RegExpRoute, NavigationRoute, Router} from 'workbox-routing';

const router = new Router();
router.registerRoute(new Route(matchCb, handlerCb));
router.registerRoute(new RegExpRoute(new RegExp(...), handlerCb));
router.registerRoute(new NavigationRoute(handlerCb));

Loại

NavigationRoute

NavigationRoute giúp bạn dễ dàng tạo workbox-routing.Route phù hợp với trình duyệt [yêu cầu chỉ đường]https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading#first_what_are_navigation_requests.

Yêu cầu này sẽ chỉ khớp với các Yêu cầu đến có https://fetch.spec.whatwg.org/#concept-request-mode|mode được đặt thành navigate.

Bạn chỉ có thể áp dụng tuyến này cho một số yêu cầu chỉ đường (không bắt buộc) bằng cách sử dụng một hoặc cả hai tham số denylistallowlist.

Thuộc tính

  • hàm khởi tạo

    void

    Nếu bạn cung cấp cả denylistallowlist, thì denylist sẽ sẽ được ưu tiên và yêu cầu sẽ không khớp với tuyến này.

    Biểu thức chính quy trong allowlistdenylist khớp với các chuỗi được nối [pathname]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname và [search]https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search của URL được yêu cầu.

    Lưu ý: Các RegExps này có thể được đánh giá dựa trên mọi URL đích trong khoảng thời gian điều hướng. Tránh sử dụng RegExps phức tạp, nếu không, người dùng có thể gặp phải sự chậm trễ khi điều hướng trang web của bạn.

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

    (handler: RouteHandler, options?: NavigationRouteMatchOptions) => {...}

  • catchHandler

    RouteHandlerObject không bắt buộc

  • trình xử lý
  • phù hợp
  • method

    HTTPMethod

  • setCatchHandler

    void

    Hàm setCatchHandler có dạng như sau:

    (handler: RouteHandler) => {...}

    • trình xử lý

      Lệnh gọi lại hàm trả về một Promise phân giải cho một Phản hồi

NavigationRouteMatchOptions

Thuộc tính

  • danh sách cho phép

    RegExp[] không bắt buộc

  • danh sách từ chối

    RegExp[] không bắt buộc

RegExpRoute

RegExpRoute giúp bạn dễ dàng tạo biểu thức chính quy dựa trên workbox-routing.Route.

Đối với các yêu cầu cùng nguồn gốc, RegExp chỉ cần khớp với một phần của URL. Cho đối với máy chủ của bên thứ ba, bạn phải xác định RegExp phù hợp với phần đầu của URL.

Thuộc tính

  • hàm khởi tạo

    void

    Nếu biểu thức chính quy chứa [nhóm chụp]https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references, các giá trị đã thu thập sẽ được chuyển đến params workbox-routing~handlerCallback đối số.

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

    (regExp: RegExp, handler: RouteHandler, method?: HTTPMethod) => {...}

    • regExp

      RegExp

      Biểu thức chính quy để so khớp với URL.

    • trình xử lý

      Lệnh gọi lại hàm trả về Lời hứa dẫn đến Phản hồi.

    • method

      HTTPMethod không bắt buộc

  • catchHandler

    RouteHandlerObject không bắt buộc

  • trình xử lý
  • phù hợp
  • method

    HTTPMethod

  • setCatchHandler

    void

    Hàm setCatchHandler có dạng như sau:

    (handler: RouteHandler) => {...}

    • trình xử lý

      Lệnh gọi lại hàm trả về một Promise phân giải cho một Phản hồi

Route

Route bao gồm một cặp hàm callback là "match" ("khớp") và "handler". "Trùng khớp" lệnh gọi lại xác định xem có nên sử dụng một tuyến để "xử lý" hay không một bằng cách trả về một giá trị không sai (nếu có thể). "Người xử lý" số gọi lại được gọi khi có kết quả trùng khớp và sẽ trả về một Lời hứa đã giải quyết thành Response.

Thuộc tính

  • hàm khởi tạo

    void

    Hàm khởi tạo cho lớp Tuyến đường.

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

    (match: RouteMatchCallback, handler: RouteHandler, method?: HTTPMethod) => {...}

    • phù hợp

      Hàm callback xác định xem tuyến có khớp với một hàm đã cho hay không fetch bằng cách trả về một giá trị không giả.

    • trình xử lý

      Lệnh gọi lại hàm trả về một Promise phân giải cho một Phản hồi.

    • method

      HTTPMethod không bắt buộc

  • catchHandler

    RouteHandlerObject không bắt buộc

  • trình xử lý
  • phù hợp
  • method

    HTTPMethod

  • setCatchHandler

    void

    Hàm setCatchHandler có dạng như sau:

    (handler: RouteHandler) => {...}

    • trình xử lý

      Lệnh gọi lại hàm trả về một Promise phân giải cho một Phản hồi

Router

Bạn có thể dùng Bộ định tuyến để xử lý FetchEvent bằng một hoặc nhiều workbox-routing.Route, phản hồi bằng Response nếu tuyến đường phù hợp đã tồn tại.

Nếu không có tuyến nào khớp với một yêu cầu đã cho, Bộ định tuyến sẽ sử dụng giá trị "mặc định" nếu một trình xử lý được xác định.

Nếu Tuyến đường phù hợp gửi lỗi, Bộ định tuyến sẽ sử dụng "catch" nếu một trình xử lý được xác định là xử lý linh hoạt các vấn đề và phản hồi bằng Yêu cầu.

Nếu một yêu cầu khớp với nhiều tuyến, thì tuyến đường được đăng ký sớm nhất sẽ để phản hồi yêu cầu.

Thuộc tính

  • hàm khởi tạo

    void

    Khởi chạy Bộ định tuyến mới.

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

    () => {...}

  • tuyến đường

    Map&lt;HTTPMethodRoute[]&gt;

  • addCacheListener

    void

    Thêm trình nghe sự kiện thông báo cho các URL để lưu vào bộ nhớ đệm trong cửa sổ. Điều này rất hữu ích để lưu các tài nguyên vào bộ nhớ đệm được tải trên trang trước khi Service worker đã bắt đầu kiểm soát nó.

    Định dạng của dữ liệu tin nhắn được gửi từ cửa sổ phải như sau. Trong đó mảng urlsToCache có thể bao gồm các chuỗi URL hoặc một mảng Chuỗi URL + đối tượng requestInit (giống như cách bạn truyền đến fetch()).

    {
      type: 'CACHE_URLS',
      payload: {
        urlsToCache: [
          './script1.js',
          './script2.js',
          ['./script3.js', {mode: 'no-cors'}],
        ],
      },
    }
    

    Hàm addCacheListener có dạng như sau:

    () => {...}

  • addFetchListener

    void

    Thêm trình nghe sự kiện tìm nạp để phản hồi các sự kiện khi một tuyến khớp yêu cầu của sự kiện.

    Hàm addFetchListener có dạng như sau:

    () => {...}

  • findMatchingRoute

    void

    Kiểm tra yêu cầu và URL (và một sự kiện không bắt buộc) so với danh sách các tuyến đã đăng ký và nếu có kết quả trùng khớp, hàm sẽ trả về giá trị cùng với mọi tham số do việc so khớp tạo ra.

    Hàm findMatchingRoute có dạng như sau:

    (options: RouteMatchCallbackOptions) => {...}

    • returns

      đối tượng

      Một đối tượng có các thuộc tính routeparams. Các đường dẫn này sẽ được điền sẵn nếu tìm thấy một tuyến đường trùng khớp hoặc undefined nếu không.

  • handleRequest

    void

    Áp dụng các quy tắc định tuyến cho một đối tượng FetchEvent để nhận Phản hồi từ một đối tượng trình xử lý của Tuyến đường thích hợp.

    Hàm handleRequest có dạng như sau:

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

    • tùy chọn

      đối tượng

      • event

        ExtendableEvent

        Sự kiện đã kích hoạt của bạn.

      • request

        Yêu cầu

        Yêu cầu xử lý.

    • returns

      Promise&lt;Response&gt;

      Lời hứa được trả lại nếu có thể xử lý yêu cầu. Nếu không có mã nào phù hợp tuyến và không có defaultHandler, thì kết quả trả về là undefined.

  • registerRoute

    void

    Đăng ký một tuyến với bộ định tuyến.

    Hàm registerRoute có dạng như sau:

    (route: Route) => {...}

    • tuyến đường

      Tuyến đường đăng ký.

  • setCatchHandler

    void

    Nếu Tuyến đường gửi lỗi trong khi xử lý yêu cầu, thì handler này sẽ được gọi và cho bạn cơ hội phản hồi.

    Hàm setCatchHandler có dạng như sau:

    (handler: RouteHandler) => {...}

    • trình xử lý

      Lệnh gọi lại hàm trả về Lời hứa dẫn đến Phản hồi.

  • setDefaultHandler

    void

    Xác định handler mặc định được gọi khi không có tuyến đường rõ ràng nào khớp với yêu cầu đến.

    Mỗi phương thức HTTP ('GET', 'POST', v.v.) đều có trình xử lý mặc định riêng.

    Nếu không có trình xử lý mặc định, các yêu cầu không khớp sẽ chống lại mạng như thể không có trình chạy dịch vụ nào.

    Hàm setDefaultHandler có dạng như sau:

    (handler: RouteHandler, method?: HTTPMethod) => {...}

    • trình xử lý

      Lệnh gọi lại hàm trả về Lời hứa dẫn đến Phản hồi.

    • method

      HTTPMethod không bắt buộc

  • unregisterRoute

    void

    Huỷ đăng ký một tuyến đường với bộ định tuyến.

    Hàm unregisterRoute có dạng như sau:

    (route: Route) => {...}

    • tuyến đường

      Tuyến đường cần huỷ đăng ký.

Phương thức

registerRoute()

workbox-routing.registerRoute(
  capture: string | RegExp | RouteMatchCallback | Route,
  handler?: RouteHandler,
  method?: HTTPMethod,
)

Dễ dàng đăng ký RegExp, chuỗi hoặc hàm bằng chức năng lưu vào bộ nhớ đệm cho thực thể bộ định tuyến singleton.

Phương thức này sẽ tạo một Tuyến đường cho bạn nếu cần và gọi workbox-routing.Router#registerRoute.

Tham số

  • chụp

    string | RegExp | RouteMatchCallback | Tuyến đường

    Nếu thông số thu thập là Route, mọi đối số khác sẽ bị bỏ qua.

  • trình xử lý

    RouteHandler không bắt buộc

  • method

    HTTPMethod không bắt buộc

Giá trị trả về

setCatchHandler()

workbox-routing.setCatchHandler(
  handler: RouteHandler,
)

Nếu Tuyến đường gửi lỗi trong khi xử lý yêu cầu, thì handler này sẽ được gọi và cho bạn cơ hội phản hồi.

Tham số

  • trình xử lý

    Lệnh gọi lại hàm trả về Lời hứa dẫn đến Phản hồi.

setDefaultHandler()

workbox-routing.setDefaultHandler(
  handler: RouteHandler,
)

Xác định handler mặc định được gọi khi không có tuyến đường rõ ràng nào khớp với yêu cầu đến.

Nếu không có trình xử lý mặc định, các yêu cầu không khớp sẽ chống lại mạng như thể không có trình chạy dịch vụ nào.

Tham số

  • trình xử lý

    Lệnh gọi lại hàm trả về Lời hứa dẫn đến Phản hồi.