Cách trình chạy web và trình chạy dịch vụ có thể cải thiện hiệu suất của trang web, cũng như thời điểm sử dụng trình chạy web so với trình chạy dịch vụ.
Thông tin tổng quan này giải thích cách worker web và worker dịch vụ có thể cải thiện hiệu suất của trang web, cũng như thời điểm sử dụng worker web so với worker dịch vụ. Hãy xem phần còn lại của loạt bài này để biết các mẫu cụ thể về giao tiếp giữa cửa sổ và worker dịch vụ.
Cách worker có thể cải thiện trang web của bạn
Trình duyệt sử dụng một luồng duy nhất (luồng chính) để chạy tất cả JavaScript trong một trang web, cũng như để thực hiện các tác vụ như hiển thị trang và thu gom rác. Việc chạy quá nhiều mã JavaScript có thể chặn luồng chính, khiến trình duyệt trì hoãn việc thực hiện các tác vụ này và dẫn đến trải nghiệm người dùng kém.
Trong quá trình phát triển ứng dụng iOS/Android, một mẫu phổ biến để đảm bảo luồng chính của ứng dụng vẫn có thể phản hồi các sự kiện của người dùng là chuyển các thao tác sang các luồng bổ sung. Trên thực tế, trong các phiên bản Android mới nhất, việc chặn luồng chính quá lâu sẽ dẫn đến sự cố ứng dụng.
Trên web, JavaScript được thiết kế dựa trên khái niệm về một luồng và thiếu các chức năng cần thiết để triển khai mô hình nhiều luồng như mô hình mà các ứng dụng có, chẳng hạn như bộ nhớ dùng chung.
Mặc dù có những hạn chế này, nhưng bạn vẫn có thể đạt được một mẫu tương tự trên web bằng cách sử dụng worker để chạy tập lệnh trong luồng nền, cho phép các worker thực hiện tác vụ mà không can thiệp vào luồng chính. Worker là toàn bộ phạm vi JavaScript chạy trên một luồng riêng biệt, không có bộ nhớ dùng chung.
Trong bài đăng này, bạn sẽ tìm hiểu về hai loại worker (worker web và worker dịch vụ), điểm giống và khác nhau giữa các worker này cũng như các mẫu phổ biến nhất để sử dụng worker trong trang web chính thức.

Trình chạy web và trình chạy dịch vụ
Điểm tương đồng
Trình chạy web và trình chạy dịch vụ là hai loại trình chạy có sẵn cho trang web. Các loại này có một số điểm chung:
- Cả hai đều chạy trong luồng phụ, cho phép mã JavaScript thực thi mà không chặn luồng chính và giao diện người dùng.
- Các đối tượng này không có quyền truy cập vào đối tượng
Window
vàDocument
, vì vậy, chúng không thể tương tác trực tiếp với DOM và có quyền truy cập hạn chế vào API trình duyệt.
Sự khác biệt
Bạn có thể nghĩ rằng hầu hết những việc có thể được uỷ quyền cho một worker web đều có thể được thực hiện trong một worker dịch vụ và ngược lại, nhưng có những điểm khác biệt quan trọng giữa chúng:
- Không giống như worker web, worker dịch vụ cho phép bạn chặn các yêu cầu mạng (thông qua sự kiện
fetch
) và nghe các sự kiện API đẩy ở chế độ nền (thông qua sự kiệnpush
). - Một trang có thể tạo nhiều trình chạy web, nhưng một trình chạy dịch vụ duy nhất sẽ kiểm soát tất cả các thẻ đang hoạt động trong phạm vi mà trình chạy dịch vụ đó được đăng ký.
- Vòng đời của worker web được ghép nối chặt chẽ với thẻ mà worker đó thuộc về, trong khi vòng đời của worker dịch vụ lại độc lập với vòng đời của worker web. Vì lý do đó, việc đóng thẻ mà trình chạy web đang chạy sẽ chấm dứt trình chạy đó, trong khi trình chạy dịch vụ có thể tiếp tục chạy ở chế độ nền, ngay cả khi trang web không có thẻ nào đang mở.
Trường hợp sử dụng
Sự khác biệt giữa cả hai loại worker cho biết trong trường hợp nào bạn nên sử dụng loại worker này hoặc loại worker kia:
Các trường hợp sử dụng worker web thường liên quan đến việc giảm tải công việc (chẳng hạn như các phép tính tốn kém) sang luồng phụ để tránh chặn giao diện người dùng.

- Ví dụ: nhóm đã tạo trò chơi điện tử PROXX muốn để luồng chính được tự do nhất có thể để xử lý hoạt ảnh và dữ liệu đầu vào của người dùng. Để đạt được điều đó, họ đã sử dụng trình chạy web để chạy logic trò chơi và duy trì trạng thái trên một luồng riêng biệt.

Các tác vụ của trình chạy dịch vụ thường liên quan nhiều hơn đến việc đóng vai trò là proxy mạng, xử lý các tác vụ trong nền và những việc như lưu vào bộ nhớ đệm và ngoại tuyến.

Ví dụ: Trong một PWA podcast, bạn có thể muốn cho phép người dùng tải các tập đầy đủ xuống để nghe khi không có mạng. Bạn có thể sử dụng trình chạy dịch vụ và cụ thể là Background Fetch API (API Tìm nạp trong nền) cho mục đích đó. Nhờ đó, nếu người dùng đóng thẻ trong khi tập đang tải xuống, thì tác vụ sẽ không bị gián đoạn.

Công cụ và thư viện
Bạn có thể triển khai giao tiếp giữa cửa sổ và worker bằng cách sử dụng nhiều API cấp thấp hơn. May mắn thay, có các thư viện tóm tắt quy trình này, xử lý các trường hợp sử dụng phổ biến nhất. Trong phần này, chúng ta sẽ đề cập đến hai trong số đó, tương ứng là Comlink và Workbox. Các công cụ này sẽ xử lý cửa sổ cho worker web và worker dịch vụ.

Comlink
Comlink là một thư viện RPC nhỏ (1,6k) giúp xử lý nhiều thông tin chi tiết cơ bản khi xây dựng các trang web sử dụng Web Worker. Công cụ này đã được sử dụng trong các trang web như PROXX và Squoosh. Bạn có thể xem bản tóm tắt về lý do và mã mẫu của thư viện này tại đây.
Workbox
Workbox là một thư viện phổ biến để xây dựng các trang web sử dụng worker dịch vụ. Thư viện này đóng gói một bộ các phương pháp hay nhất liên quan đến các hoạt động như lưu vào bộ nhớ đệm, ngoại tuyến, đồng bộ hoá trong nền, v.v. Mô-đun workbox-window
cung cấp một cách thuận tiện để trao đổi thông báo giữa worker dịch vụ và trang.
Các bước tiếp theo
Phần còn lại của loạt bài này tập trung vào các mẫu giao tiếp giữa cửa sổ và worker dịch vụ:
- Hướng dẫn bắt buộc về việc lưu vào bộ nhớ đệm: Gọi trình chạy dịch vụ từ trang để lưu trước tài nguyên vào bộ nhớ đệm (ví dụ: trong các trường hợp tải trước).
- Phát đi thông tin cập nhật: Gọi trang từ worker dịch vụ để thông báo về các nội dung cập nhật quan trọng (ví dụ: có phiên bản mới của trang web).
- Thông tin liên lạc hai chiều: Uỷ quyền một tác vụ cho worker dịch vụ (ví dụ: tải xuống nhiều dữ liệu) và thông báo cho trang về tiến trình.
Để biết các mẫu giao tiếp giữa cửa sổ và worker web, hãy xem bài viết: Sử dụng worker web để chạy JavaScript ngoài luồng chính của trình duyệt.