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 nên sử dụng trình chạy web so với trình chạy dịch vụ.
Nội dung tổng quan này giải thích 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ụ. Hãy xem phần còn lại của loạt bài này để biết các mẫu giao tiếp cụ thể giữa cửa sổ và trình chạy dịch vụ.
Cách trình chạy 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ư kết xuất 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 chậm 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/ứng dụng Android, một mẫu phổ biến để đảm bảo rằng luồng chính của ứng dụng luôn sẵn sàng phản hồi các sự kiện của người dùng là giảm tải 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ẽ khiến ứng dụng gặp sự cố.
Trên web, JavaScript được thiết kế dựa trên khái niệm về một luồng duy nhất và thiếu các chức năng cần thiết để triển khai mô hình đa luồng như các ứng dụng có, chẳng hạn như bộ nhớ dùng chung.
Bất chấp những hạn chế này, bạ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 chúng thực hiện các tác vụ mà không can thiệp vào luồng chính. Worker là một phạm vi JavaScript hoàn chỉnh 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 trình chạy khác nhau (trình chạy web và trình chạy dịch vụ), điểm tương đồng và khác biệt giữa chúng, cũng như các mẫu phổ biến nhất để sử dụng chúng trong các 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 các trang web. Các ứng dụng này có một số điểm chung:
- Cả hai đều chạy trong một 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
WindowvàDocument, nên 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 các API trình duyệt.
Sự khác biệt
Người ta có thể nghĩ rằng hầu hết những việc có thể uỷ quyền cho một trình chạy web đều có thể thực hiện trong một trình chạy 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ư trình chạy web, trình chạy 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à theo dõi các sự kiện Push API trong nền (thông qua sự kiệnpush). - Một trang có thể tạo ra 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 trình chạy web gắn liền với thẻ chứa trình chạy đó, trong khi vòng đời của trình chạy dịch vụ độc lập với thẻ. Vì lý do đó, việc đóng thẻ nơi 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 hai loại worker cho thấy những trường hợp mà bạn có thể muốn sử dụng loại này hoặc loại kia:
Các trường hợp sử dụng cho trình chạy web thường liên quan đến việc giảm tải công việc (như tính toán nặng) sang một luồng phụ để tránh chặn giao diện người dùng.
- Ví dụ: nhóm xây dựng trò chơi điện tử PROXX muốn để luồng chính rảnh rỗi nhất có thể để xử lý hoạt ảnh và hoạt động đầ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.
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 xuống các tập hoàn chỉnh để nghe khi không có mạng. Bạn có thể sử dụng một trình chạy dịch vụ, cụ thể là Background Fetch API (API Tìm nạp ở chế độ nền) để thực hiện việc này. Bằng cách đó, nếu người dùng đóng thẻ trong khi tập podcast đ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 hoạt động giao tiếp giữa cửa sổ và worker bằng cách sử dụng các API cấp thấp hơn. May mắn là 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 thư viện đảm nhận việc giao tiếp giữa cửa sổ với trình chạy web và trình chạy dịch vụ: Comlink và Workbox.
Comlink
Comlink là một thư viện RPC nhỏ (1,6k) đảm nhận nhiều chi tiết cơ bản khi xây dựng trang web sử dụng Web Worker. Nó đã được sử dụng trong các trang web như PROXX và Squoosh. Bạn có thể xem thông tin tóm tắt về động lực và mã mẫu 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 trình chạy dịch vụ. Mô-đun này đóng gói một tập hợp các phương pháp hay nhất về những việc 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 trình chạy 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à trình chạy dịch vụ:
- Hướng dẫn lưu vào bộ nhớ đệm bắt buộc: Gọi một 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ìm nạp trước).
- Thông báo nội dung cập nhật: Gọi trang từ trình chạy 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).
- Giao tiếp hai chiều: Giao nhiệm vụ cho một trình chạy dịch vụ (ví dụ: tải xuống tệp nặng) 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à trình chạy web, hãy xem bài viết: Sử dụng trình chạy web để chạy JavaScript ngoài luồng chính của trình duyệt.