Hiển thị HTML và tính tương tác phía máy khách

Việc kết xuất HTML bằng JavaScript khác với việc kết xuất HTML do máy chủ gửi và điều này có thể ảnh hưởng đến hiệu suất. Tìm hiểu sự khác biệt trong hướng dẫn này và những việc bạn có thể làm để duy trì hiệu suất kết xuất của trang web, đặc biệt là khi liên quan đến hoạt động tương tác.

Theo mặc định, trình duyệt thực hiện rất tốt việc phân tích cú pháp và hiển thị HTML cho các trang web sử dụng logic điều hướng tích hợp sẵn của trình duyệt – đôi khi được gọi là "tải trang truyền thống" hoặc "điều hướng cứng". Những trang web như vậy đôi khi được gọi là ứng dụng nhiều trang (MPA).

Tuy nhiên, nhà phát triển có thể điều chỉnh các chế độ mặc định của trình duyệt cho phù hợp với nhu cầu của ứng dụng. Đây chắc chắn là trường hợp đối với các trang web sử dụng mẫu ứng dụng một trang (SPA). Mẫu này tạo linh động phần lớn HTML/DOM trên máy khách bằng JavaScript. Kết xuất phía máy khách là tên của mẫu thiết kế này và có thể ảnh hưởng đến Lượt tương tác đến nội dung hiển thị tiếp theo (INP) của trang web nếu công việc liên quan quá mức.

Hướng dẫn này sẽ giúp bạn cân nhắc sự khác biệt giữa việc sử dụng HTML do máy chủ gửi đến trình duyệt so với việc tạo HTML trên ứng dụng bằng JavaScript, cũng như cách cách sau có thể dẫn đến độ trễ tương tác cao tại những thời điểm quan trọng.

Cách trình duyệt hiển thị HTML do máy chủ cung cấp

Mẫu điều hướng được dùng trong quá trình tải trang truyền thống liên quan đến việc nhận HTML từ máy chủ trên mỗi thao tác điều hướng. Nếu bạn nhập một URL vào thanh địa chỉ của trình duyệt hoặc nhấp vào một đường liên kết trong MPA, thì một loạt sự kiện sau sẽ xảy ra:

  1. Trình duyệt gửi yêu cầu điều hướng cho URL đã cung cấp.
  2. Máy chủ phản hồi bằng HTML theo từng phần.

Bước cuối cùng trong số này là bước quan trọng nhất. Đây cũng là một trong những phương pháp tối ưu hoá hiệu suất cơ bản nhất trong quá trình trao đổi máy chủ/trình duyệt và được gọi là truyền trực tuyến. Nếu máy chủ có thể bắt đầu gửi HTML càng sớm càng tốt và trình duyệt không chờ toàn bộ phản hồi đến, thì trình duyệt có thể xử lý HTML theo từng phần khi nhận được.

Ảnh chụp màn hình về quá trình phân tích cú pháp HTML do máy chủ gửi được hiển thị trong bảng hiệu suất của Công cụ của Chrome cho nhà phát triển. Khi HTML truyền vào, các phần của HTML được xử lý trên nhiều tác vụ ngắn hơn và quá trình kết xuất sẽ tăng dần.
Quá trình phân tích cú pháp và hiển thị HTML do máy chủ cung cấp như được minh hoạ trong bảng hiệu suất của Chrome DevTools. Các tác vụ liên quan đến việc phân tích cú pháp HTML và hiển thị HTML được chia thành các phần.

Giống như hầu hết các hoạt động diễn ra trong trình duyệt, việc phân tích cú pháp HTML cũng diễn ra trong các tác vụ. Khi HTML được truyền trực tuyến từ máy chủ đến trình duyệt, trình duyệt sẽ tối ưu hoá việc phân tích cú pháp HTML đó bằng cách phân tích cú pháp từng bit một khi các bit của luồng đó đến theo từng phần. Kết quả là trình duyệt sẽ định kỳ trả về luồng chính sau khi xử lý từng phần, giúp tránh các tác vụ dài. Điều này có nghĩa là các tác vụ khác có thể xảy ra trong khi HTML đang được phân tích cú pháp, bao gồm cả tác vụ kết xuất gia tăng cần thiết để hiển thị trang cho người dùng, cũng như xử lý các hoạt động tương tác của người dùng có thể xảy ra trong giai đoạn khởi động quan trọng của trang. Phương pháp này giúp trang có điểm số Lượt tương tác đến nội dung hiển thị tiếp theo (INP) cao hơn.

Bạn cần lưu ý điều gì? Khi truyền trực tuyến HTML từ máy chủ, bạn sẽ nhận được tính năng phân tích cú pháp và hiển thị HTML gia tăng, đồng thời tự động chuyển sang luồng chính mà không mất phí. Bạn không nhận được điều đó khi kết xuất phía máy khách.

Cách trình duyệt hiển thị HTML do JavaScript cung cấp

Mặc dù mỗi yêu cầu điều hướng đến một trang đều yêu cầu máy chủ cung cấp một lượng HTML nhất định, nhưng một số trang web sẽ sử dụng mẫu SPA. Phương pháp này thường liên quan đến tải trọng ban đầu tối thiểu của HTML do máy chủ cung cấp, nhưng sau đó ứng dụng sẽ điền sẵn HTML được tập hợp từ dữ liệu được tìm nạp từ máy chủ vào khu vực nội dung chính của trang. Các thao tác điều hướng tiếp theo (đôi khi được gọi là "điều hướng mềm" trong trường hợp này) do JavaScript xử lý hoàn toàn để điền HTML mới vào trang.

Quá trình kết xuất phía máy khách cũng có thể xảy ra trong các ứng dụng không phải SPA trong một số ít trường hợp, khi HTML được thêm vào DOM một cách linh động thông qua JavaScript.

Có một số cách phổ biến để tạo HTML hoặc thêm vào DOM thông qua JavaScript:

  1. Thuộc tính innerHTML cho phép bạn đặt nội dung trên một phần tử hiện có thông qua một chuỗi mà trình duyệt sẽ phân tích cú pháp thành DOM.
  2. Phương thức document.createElement cho phép bạn tạo các phần tử mới để thêm vào DOM mà không cần sử dụng bất kỳ tính năng phân tích cú pháp HTML nào của trình duyệt.
  3. Phương thức document.write cho phép bạn ghi HTML vào tài liệu (và trình duyệt sẽ phân tích cú pháp tài liệu đó, giống như trong phương pháp #1). Tuy nhiên, do một số lý do, bạn không nên sử dụng document.write.
Ảnh chụp màn hình về quá trình phân tích cú pháp HTML được kết xuất thông qua JavaScript được hiển thị trong bảng điều khiển hiệu suất của Công cụ dành cho nhà phát triển của Chrome. Công việc diễn ra trong một tác vụ dài, chặn luồng chính.
Quá trình phân tích cú pháp và hiển thị HTML thông qua JavaScript trên máy khách như được minh hoạ trong bảng hiệu suất của Công cụ cho nhà phát triển của Chrome. Các tác vụ liên quan đến việc phân tích cú pháp và hiển thị không được chia thành các phần, dẫn đến một tác vụ dài chặn luồng chính.

Việc tạo HTML/DOM thông qua JavaScript phía máy khách có thể gây ra những hậu quả đáng kể:

  • Không giống như HTML do máy chủ truyền trực tuyến để phản hồi yêu cầu điều hướng, các tác vụ JavaScript trên máy khách không tự động được phân đoạn, điều này có thể dẫn đến các tác vụ dài chặn luồng chính. Điều này có nghĩa là INP của trang có thể bị ảnh hưởng tiêu cực nếu bạn tạo quá nhiều HTML/DOM cùng một lúc trên máy khách.
  • Nếu HTML được tạo trên máy khách trong quá trình khởi động, thì trình quét tải trước của trình duyệt sẽ không phát hiện được các tài nguyên được tham chiếu trong đó. Điều này chắc chắn sẽ ảnh hưởng tiêu cực đến Thời gian hiển thị nội dung lớn nhất (LCP) của trang. Mặc dù đây không phải là vấn đề về hiệu suất trong thời gian chạy (mà là vấn đề về độ trễ mạng trong việc tìm nạp các tài nguyên quan trọng), nhưng bạn không muốn LCP của trang web bị ảnh hưởng do bỏ qua hoạt động tối ưu hoá hiệu suất cơ bản của trình duyệt này.

Những việc bạn có thể làm về tác động của hiệu suất khi kết xuất phía máy khách

Nếu trang web của bạn phụ thuộc nhiều vào tính năng kết xuất phía máy khách và bạn nhận thấy các giá trị INP kém trong dữ liệu trường, thì bạn có thể thắc mắc liệu tính năng kết xuất phía máy khách có liên quan gì đến vấn đề này hay không. Ví dụ: nếu trang web của bạn là một SPA, thì dữ liệu trường có thể cho thấy các lượt tương tác chịu trách nhiệm cho công việc kết xuất đáng kể.

Dù nguyên nhân là gì, sau đây là một số nguyên nhân có thể xảy ra mà bạn có thể tìm hiểu để giúp mọi thứ trở lại đúng hướng.

Cung cấp càng nhiều HTML từ máy chủ càng tốt

Như đã đề cập trước đó, theo mặc định, trình duyệt xử lý HTML từ máy chủ theo cách rất hiệu quả. Phương thức này sẽ chia nhỏ quá trình phân tích cú pháp và hiển thị HTML theo cách tránh các tác vụ dài và tối ưu hoá tổng thời gian của luồng chính. Điều này dẫn đến Tổng thời gian chặn (TBT) thấp hơn và TBT có mối tương quan chặt chẽ với INP.

Bạn có thể đang dựa vào một khung giao diện người dùng để xây dựng trang web. Nếu có, bạn cần đảm bảo rằng bạn đang kết xuất HTML thành phần trên máy chủ. Điều này sẽ giới hạn lượng kết xuất ban đầu phía máy khách mà trang web của bạn yêu cầu, đồng thời mang lại trải nghiệm tốt hơn.

  • Đối với React, bạn nên sử dụng Server DOM API để hiển thị HTML trên máy chủ. Tuy nhiên, hãy lưu ý: phương thức hiển thị phía máy chủ truyền thống sử dụng phương pháp đồng bộ, điều này có thể dẫn đến Thời gian cho byte đầu tiên (TTFB) lâu hơn, cũng như các chỉ số tiếp theo như Hiển thị nội dung đầu tiên (FCP) và LCP. Nếu có thể, hãy đảm bảo bạn đang sử dụng các API truyền trực tuyến cho Node.js hoặc các môi trường thời gian chạy JavaScript khác để máy chủ có thể bắt đầu truyền trực tuyến HTML đến trình duyệt càng sớm càng tốt. Next.js – một khung dựa trên React – cung cấp nhiều phương pháp hay nhất theo mặc định. Ngoài việc tự động hiển thị HTML trên máy chủ, trình này cũng có thể tạo HTML tĩnh cho các trang không thay đổi dựa trên ngữ cảnh người dùng (chẳng hạn như xác thực).
  • Theo mặc định, Vue cũng thực hiện kết xuất phía máy khách. Tuy nhiên, giống như React, Vue cũng có thể hiển thị HTML thành phần trên máy chủ. Hãy tận dụng các API phía máy chủ này khi có thể hoặc cân nhắc tính trừu tượng cấp cao hơn cho dự án Vue để dễ dàng triển khai các phương pháp hay nhất.
  • Theo mặc định, Svelte hiển thị HTML trên máy chủ – mặc dù nếu mã thành phần của bạn cần quyền truy cập vào không gian tên dành riêng cho trình duyệt (ví dụ: window), thì bạn có thể không thể hiển thị HTML của thành phần đó trên máy chủ. Hãy tìm hiểu các phương pháp thay thế bất cứ khi nào có thể để không gây ra quá trình kết xuất phía máy khách không cần thiết. SvelteKit (dành cho Svelte như Next.js dành cho React) nhúng nhiều phương pháp hay nhất vào các dự án Svelte của bạn càng tốt, nhờ đó bạn có thể tránh được những sai lầm tiềm ẩn trong các dự án chỉ sử dụng Svelte.

Giới hạn số lượng nút DOM được tạo trên máy khách

Khi DOM lớn, lượng dữ liệu cần xử lý để hiển thị DOM đó có xu hướng tăng lên. Cho dù trang web của bạn là một SPA đầy đủ chức năng hay đang chèn các nút mới vào một DOM hiện có do kết quả của một lượt tương tác cho MPA, hãy cân nhắc việc giữ cho các DOM đó càng nhỏ càng tốt. Điều này sẽ giúp giảm công việc cần thực hiện trong quá trình kết xuất phía máy khách để hiển thị HTML đó, hy vọng sẽ giúp giảm INP của trang web.

Cân nhắc kiến trúc worker của dịch vụ phát trực tuyến

Đây là một kỹ thuật nâng cao – một kỹ thuật có thể không dễ dàng áp dụng cho mọi trường hợp sử dụng – nhưng có thể biến MPA của bạn thành một trang web có cảm giác như đang tải ngay lập tức khi người dùng di chuyển từ trang này sang trang khác. Bạn có thể sử dụng trình chạy dịch vụ để lưu các phần tĩnh của trang web vào bộ nhớ đệm trước trong CacheStorage trong khi sử dụng ReadableStream API để tìm nạp phần còn lại của HTML của trang từ máy chủ.

Khi sử dụng thành công kỹ thuật này, bạn không tạo HTML trên máy khách, nhưng việc tải tức thì các phần nội dung từ bộ nhớ đệm sẽ tạo cảm giác trang web của bạn đang tải nhanh. Các trang web sử dụng phương pháp này có thể gần giống như một SPA, nhưng không có những điểm yếu của tính năng kết xuất phía máy khách. Việc này cũng giảm lượng HTML mà bạn yêu cầu từ máy chủ.

Tóm lại, cấu trúc worker của dịch vụ phát trực tuyến không thay thế logic điều hướng tích hợp sẵn của trình duyệt mà thêm vào logic đó. Để biết thêm thông tin về cách thực hiện việc này bằng Workbox, hãy đọc bài viết Ứng dụng nhiều trang nhanh hơn bằng luồng.

Kết luận

Cách trang web nhận và hiển thị HTML có tác động đến hiệu suất. Khi dựa vào máy chủ để gửi tất cả (hoặc phần lớn) HTML cần thiết cho trang web của bạn hoạt động, bạn sẽ nhận được nhiều lợi ích miễn phí: phân tích cú pháp và hiển thị gia tăng, đồng thời tự động chuyển sang luồng chính để tránh các tác vụ dài.

Việc kết xuất HTML phía máy khách có thể gây ra một số vấn đề về hiệu suất có thể tránh được trong nhiều trường hợp. Tuy nhiên, do các yêu cầu của từng trang web, bạn không thể tránh hoàn toàn việc này 100% thời gian. Để giảm thiểu các tác vụ dài tiềm ẩn có thể xảy ra do quá trình kết xuất trang web của máy khách, hãy đảm bảo bạn gửi càng nhiều HTML của trang web từ máy chủ càng tốt, giữ kích thước DOM càng nhỏ càng tốt cho HTML phải được kết xuất trên máy khách và cân nhắc các cấu trúc thay thế để tăng tốc độ phân phối HTML đến máy khách, đồng thời tận dụng tính năng phân tích cú pháp và kết xuất gia tăng mà trình duyệt cung cấp cho HTML được tải từ máy chủ.

Nếu có thể giảm thiểu hoạt động kết xuất phía máy khách của trang web, bạn sẽ không chỉ cải thiện INP của trang web mà còn cải thiện các chỉ số khác như LCP, TBT và thậm chí có thể là TTFB trong một số trường hợp.

Hình ảnh chính trên Unsplash, của Maik Jonietz.