Trình chạy dịch vụ có thể chặn các yêu cầu mạng cho một trang. Dịch vụ này có thể phản hồi trình duyệt bằng 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 cung cấp phản hồi.
Cách thực hiện việc định tuyến
Khi yêu cầu mạng gây ra một 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ách sử dụng các tuyến và trình xử lý đã cung cấp.
Những điều chính cần lưu ý về những điều trên là:
Phương thức của yêu cầu rất quan trọng. Theo mặc định, Tuyến đường được đăng ký cho các yêu cầu
GET
. 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à quan trọng. Nếu bạn đăng ký nhiều Tuyến đường có thể xử lý một yêu cầu, thì 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ý tuyến: bạn có thể dùng lệnh gọi lại, biểu thức chính quy hoặc thực thể Tuyến đường.
So khớp và xử lý trên tuyến đường
"Tuyến" trong hộp công việc chỉ có hai chức năng: hàm "phù hợp" để xác định xem tuyến có khớp với một yêu cầu và chức năng "xử lý" hay không. Hàm này 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ý cho bạn, nhưng nếu bạn thấy mình muốn có hành vi khác, thì tốt nhất là viết hàm so khớp và trình xử lý tuỳ chỉnh.
Hàm callback so khớp được truyền ExtendableEvent
, Request
và URL
đối tượng mà bạn có thể so khớp 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ể như sau:
const matchCb = ({url, request, event}) => {
return url.pathname === '/special/url';
};
Bạn có thể xử lý hầu hết các trường hợp sử dụng bằng cách kiểm tra / kiểm thử url
hoặc request
.
Hàm gọi lại trình xử lý sẽ được cung cấp cùng một ExtendableEvent
, Request
và URL
đối tượng cùng với giá trị params
. Đây là giá trị được hàm "match" 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 ví dụ này, chúng tôi sẽ sử dụng async
và await
.
Trong trường hợp này, giá trị trả về Response
sẽ được gói 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à lệnh gọi lại "match" (khớp) phải đồng bộ trả về một giá trị đáng tin cậy, bạn không thể thực hiện bất kỳ thao tác không đồng bộ nào. Lý do là vì Router
phải phản hồi đồng bộ sự kiện tìm nạp hoặc cho phép chuyển sang các sự kiện tìm nạp khác.
Thông thường, lệnh gọi lại "xử lý" sẽ sử dụng một trong các chiến lược do chiến lược hộp công việc cung cấp như sau:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
registerRoute(matchCb, new StaleWhileRevalidate());
Trên trang này, chúng ta sẽ tập trung vào workbox-routing
. Tuy nhiên, bạn có thể tìm hiểu thêm về các chiến lược này trong 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
Một phương pháp phổ biến là sử dụng biểu thức chính quy thay vì lệnh gọi lại "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 một 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 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 có khả năng biểu thức chính quy new RegExp('/styles/.*\\.css')
mà bạn đị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 có hành vi này, bạn chỉ cần đảm bảo rằng biểu thức chính quy khớp với phần đầu của URL. Nếu muốn so khớp các yêu cầu cho https://cdn.third-party-site.com
, chúng ta có thể sử dụng biểu thức chính quy 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 cả bên cục bộ 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 để đảm bảo không gây ra các hành vi không mong muốn trong ứng dụng web của mình.
Cách đăng ký tuyến điều hướng
Nếu trang web của bạn là ứng dụng trang đơn, bạn có thể dùng NavigationRoute
để trả về một phản hồi cụ thể cho tất cả yêu cầu điều hướ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 đối với trang sẽ là một yêu cầu điều hướng và sẽ được phân phát đến trang đã lưu trong 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 của riêng bạn.)
Theo mặc định, thao tác này sẽ phản hồi tất cả các yêu cầu chỉ đường. Nếu muốn hạn chế URL này phản hồi một nhóm nhỏ URL, bạn có thể sử dụng các tuỳ chọn allowlist
và denylist
để hạn chế những trang 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ẽ thắng nếu một URL nằm trong cả allowlist
và denylist
.
Đặt trình xử lý mặc định
Nếu muốn cung cấp "trình xử lý" cho các yêu cầu không khớp với tuyến đường, bạn có thể đặt trình xử lý mặc định.
import {setDefaultHandler} from 'workbox-routing';
setDefaultHandler(({url, event, params}) => {
// ...
});
Thiết lập Trình xử lý bắt (catch Handler)
Trong trường hợp bất kỳ tuyến nào của bạn gặp lỗi, bạn có thể nắm bắt và xuống cấp nhẹ bằng cách thiết lập trình xử lý phát hiện.
import {setCatchHandler} from 'workbox-routing';
setCatchHandler(({url, event, params}) => {
...
});
Xác định tuyến cho các yêu cầu không GET
Tất cả các tuyến theo mặc định đều được giả định là 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 có thể xác định luồng yêu cầu bằng cách sử dụng nhật ký từ
workbox-routing
, nhật ký này sẽ làm nổi bật URL nào đang được xử lý
thông qua Workbox.
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
để xem nhật ký về các yêu cầu không do Bộ định tuyến xử lý. Xem hướng dẫn gỡ lỗi của chúng tôi để biết thêm thông tin về cách đặt cấp độ nhật ký.
Cách sử dụng nâng cao
Nếu muốn có thêm quyền kiểm soát đối với thời điểm Bộ định tuyến Workbox được đưa ra yêu cầu, bạn có thể tạo thực thể Router
riêng và gọi phương thức handleRequest()
của nó bất cứ khi nào bạn muốn dùng bộ định tuyến để phản hồi 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ý các 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
[các yêu cầu điều hướng]https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading#first_what_are_navigation_requests
của trình duyệt.
Thao tác này sẽ chỉ so khớp các Yêu cầu đến có https://fetch.spec.whatwg.org/#concept-request-mode|mode
được đặt thành navigate
.
Bạn có thể tuỳ ý chỉ áp dụng tuyến này cho một nhóm nhỏ yêu cầu điều hướng bằng cách sử dụng một hoặc cả hai tham số denylist
và allowlist
.
Thuộc tính
-
void
Nếu bạn cung cấp cả
denylist
vàallowlist
, thìdenylist
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
allowlist
vàdenylist
được so khớp với các phần đã 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 ý: Bạn có thể đánh giá các biểu thức chính quy này dựa trên mọi URL đích trong quá trình điều hướng. Tránh sử dụng biểu thức chính quy phức tạp, nếu không người dùng có thể thấy độ trễ khi di chuyển trên trang web của bạn.
Hàm
constructor
sẽ có dạng như sau:(handler: RouteHandler, options?: NavigationRouteMatchOptions) => {...}
-
Một hàm callback trả về một Promise dẫn đến một Response.
-
NavigationRouteMatchOptions không bắt buộc
-
-
RouteHandlerObject không bắt buộc
-
HTTPMethod
-
void
Hàm
setCatchHandler
sẽ có dạng như sau:(handler: RouteHandler) => {...}
-
Một hàm callback trả về một Hứa hẹn sẽ giải quyết một Phản hồi
-
NavigationRouteMatchOptions
Thuộc tính
-
RegExp[] không bắt buộc
-
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ó cùng nguồn gốc, RegExp chỉ cần khớp với một phần của URL. Đối với các yêu cầu dựa trên máy chủ của bên thứ ba, bạn phải xác định một biểu thức chính quy khớ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 [capture groups]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references
, các giá trị được thu thập sẽ được chuyển đến đối sốworkbox-routing~handlerCallback
params
.Hàm
constructor
sẽ 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ý
Một hàm callback trả về một Promise dẫn đến một Response.
-
method
HTTPMethod không bắt buộc
-
giá trị trả về
-
-
catchHandler
RouteHandlerObject không bắt buộc
-
trình xử lý
-
phù hợp
-
method
HTTPMethod
-
setCatchHandler
void
Hàm
setCatchHandler
sẽ có dạng như sau:(handler: RouteHandler) => {...}
-
trình xử lý
Một hàm callback trả về một Hứa hẹn sẽ giải quyết một Phản hồi
-
Route
Route
bao gồm một cặp hàm callback, "match" và "handler".
Lệnh gọi lại "match" (so khớp) xác định xem có nên sử dụng một tuyến để "xử lý" yêu cầu bằng cách trả về một giá trị không giả mạo nếu có thể. Lệnh gọi lại "handler"
được gọi khi có kết quả trùng khớp và sẽ trả về một Promise 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
sẽ 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 sự kiện
fetch
nhất định hay không bằng cách trả về một giá trị không giả. -
trình xử lý
Một hàm callback trả về một Hứa hẹn sẽ phân giải một Phản hồi.
-
method
HTTPMethod không bắt buộc
-
giá trị trả về
-
-
catchHandler
RouteHandlerObject không bắt buộc
-
trình xử lý
-
phù hợp
-
method
HTTPMethod
-
setCatchHandler
void
Hàm
setCatchHandler
sẽ có dạng như sau:(handler: RouteHandler) => {...}
-
trình xử lý
Một hàm callback trả về một Hứa hẹn sẽ giải quyết 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 có một tuyến trùng khớp.
Nếu không có tuyến nào khớp với một yêu cầu nhất định, thì Bộ định tuyến sẽ sử dụng trình xử lý "mặc định" nếu có một trình xử lý được xác định.
Nếu Tuyến đường trùng khớp báo lỗi, Bộ định tuyến sẽ sử dụng trình xử lý "catch" nếu bạn xác định trình xử lý này là để xử lý vấn đề linh hoạt và phản hồi bằng một Yêu cầu.
Nếu một yêu cầu khớp với nhiều tuyến, thì tuyến đã đăng ký sớm nhất sẽ được dùng để 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
sẽ có dạng như sau:() => {...}
-
giá trị trả về
-
-
tuyến đường
Map<HTTPMethodRoute[]>
-
addCacheListener
void
Thêm trình nghe sự kiện thông báo cho các URL vào bộ nhớ đệm từ cửa sổ. Việc này rất hữu ích khi lưu các tài nguyên được tải trên trang vào bộ nhớ đệm trước khi trình chạy dịch vụ bắt đầu kiểm soát tài nguyên đó.
Định dạng của dữ liệu thư gửi từ cửa sổ như sau. Trong đó, mảng
urlsToCache
có thể bao gồm chuỗi URL hoặc một mảng gồm chuỗi URL + đối tượngrequestInit
(tương tự như cách bạn truyền đếnfetch()
).{ type: 'CACHE_URLS', payload: { urlsToCache: [ './script1.js', './script2.js', ['./script3.js', {mode: 'no-cors'}], ], }, }
Hàm
addCacheListener
sẽ 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 với yêu cầu của sự kiện.
Hàm
addFetchListener
sẽ có dạng như sau:() => {...}
-
findMatchingRoute
void
Kiểm tra yêu cầu và URL (và không bắt buộc là một sự kiện) dựa trên danh sách tuyến đã đăng ký và nếu có kết quả trùng khớp, hãy trả về tuyến tương ứng cùng với mọi tham số do kết quả so khớp tạo ra.
Hàm
findMatchingRoute
sẽ có dạng như sau:(options: RouteMatchCallbackOptions) => {...}
-
tùy chọn
-
giá trị trả về
đối tượng
Một đối tượng có các thuộc tính
route
vàparams
. Các giá trị này được điền sẵn nếu tìm thấy một tuyến đường trùng khớp hoặcundefined
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 được Phản hồi từ trình xử lý của Tuyến đường thích hợp.
Hàm
handleRequest
sẽ có dạng như sau:(options: object) => {...}
-
tùy chọn
đối tượng
-
event
ExtendableEvent
Sự kiện đã kích hoạt yêu cầu.
-
request
Yêu cầu
Yêu cầu được xử lý.
-
-
giá trị trả về
Hứa hẹn<Phản hồi>
Một lời hứa sẽ được trả về nếu một tuyến đã đăng ký có thể xử lý yêu cầu. Nếu không có tuyến đường nào trùng khớp và không có
defaultHandler
, thìundefined
sẽ được trả về.
-
-
registerRoute
void
Đăng ký một tuyến với bộ định tuyến.
Hàm
registerRoute
sẽ có dạng như sau:(route: Route) => {...}
-
tuyến đường
Tuyến để đăng ký.
-
-
setCatchHandler
void
Nếu một Tuyến đường báo lỗi trong khi xử lý yêu cầu, thì
handler
này sẽ được gọi và cung cấp cơ hội phản hồi.Hàm
setCatchHandler
sẽ có dạng như sau:(handler: RouteHandler) => {...}
-
trình xử lý
Một hàm callback trả về một Promise dẫn đến một Response.
-
-
setDefaultHandler
void
Xác định
handler
mặc định sẽ được gọi khi không có tuyến nào khớp rõ ràng 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 chưa khớp sẽ truy cập vào mạng như thể không có trình chạy dịch vụ nào.
Hàm
setDefaultHandler
sẽ có dạng như sau:(handler: RouteHandler, method?: HTTPMethod) => {...}
-
trình xử lý
Một hàm callback trả về một Promise dẫn đến một Response.
-
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
sẽ có dạng như sau:(route: Route) => {...}
-
tuyến đường
Tuyến đường 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 chiến lược lưu vào bộ nhớ đệm cho một 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
chuỗi | RegExp | RouteMatchCallback | Route
Nếu tham số chụp là
Route
, thì tất cả các đố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ề
-
Route
đã tạo.
setCatchHandler()
workbox-routing.setCatchHandler(
handler: RouteHandler,
)
Nếu một Tuyến đường báo lỗi trong khi xử lý yêu cầu, thì handler
này sẽ được gọi và cung cấp cơ hội phản hồi.
Tham số
-
trình xử lý
Một hàm callback trả về một Promise dẫn đến một Response.
setDefaultHandler()
workbox-routing.setDefaultHandler(
handler: RouteHandler,
)
Xác định handler
mặc định sẽ được gọi khi không có tuyến nào khớp rõ ràng 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 chưa khớp sẽ truy cập vào mạng như thể không có trình chạy dịch vụ nào.
Tham số
-
trình xử lý
Một hàm callback trả về một Promise dẫn đến một Response.