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 đó có thể ảnh hưởng đến hiệu suất. Hãy 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 hiển thị của trang web, đặc biệt là khi có các hoạt động tương tác.
Phân tích cú pháp và kết xuất HTML là những việc mà trình duyệt thực hiện rất tốt theo mặc định đối với những trang web sử dụng logic điều hướng tích hợp 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 của các trang web sử dụng mẫu ứng dụng một trang (SPA), mẫu này tạo động các phần lớn của 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 là 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 việc sử dụng HTML trên ứng dụng có thể dẫn đến độ trễ tương tác cao vào những thời điểm quan trọng.
Cách trình duyệt kết xuất HTML do máy chủ cung cấp
Mẫu điều hướng được dùng trong các lượt tải trang truyền thống liên quan đến việc nhận HTML từ máy chủ trong mỗi lượt đ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ì chuỗi sự kiện sau sẽ xảy ra:
- Trình duyệt gửi một yêu cầu điều hướng cho URL được cung cấp.
- 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 hoạt động tối ưu hoá hiệu suất cơ bản nhất trong quá trình trao đổi giữa máy chủ và trình duyệt, được gọi là truyền phát trực tiếp. Nếu máy chủ có thể bắt đầu gửi HTML sớm nhất có thể và trình duyệt không đợi toàn bộ phản hồi đến, thì trình duyệt có thể xử lý HTML theo từng phần khi phản hồi đến.

Giống như hầu hết mọi thứ xảy ra trong trình duyệt, việc phân tích cú pháp HTML 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 thực hiện từng chút một khi các phần của luồng đó đến theo từng khối. Hậu quả là trình duyệt sẽ nhường quyền cho luồng chính theo định kỳ sau khi xử lý từng khối, điều này giúp tránh các tác vụ mất nhiều thời gian. Điều này có nghĩa là các hoạt động khác có thể diễn ra trong khi HTML đang được phân tích cú pháp, bao gồm cả hoạt động kết xuất gia tăng cần thiết để trình bày một 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. Cách tiếp cận 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ẽ được phân tích cú pháp và kết xuất HTML gia tăng cũng như tự động nhường cho luồng chính miễn 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 kết xuất 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 việc máy chủ cung cấp tải trọng ban đầu tối thiểu của HTML, nhưng sau đó, ứng dụng sẽ điền vào vùng nội dung chính của một trang bằng HTML được tổng hợp từ dữ liệu được tìm nạp từ máy chủ. Các thao tác điều hướng tiếp theo (đôi khi được gọi là "thao tác điều hướng mềm" trong trường hợp này) hoàn toàn do JavaScript xử lý để đ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 trang không phải là SPA trong những trường hợp hạn chế hơn, 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:
- 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. - 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 dùng bất kỳ hoạt động phân tích cú pháp HTML nào của trình duyệt. - 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 HTML đó, 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ụngdocument.write
.

Hậu quả của việc tạo HTML/DOM thông qua JavaScript phía máy khách có thể rất nghiêm trọng:
- Không giống như HTML được truyền trực tuyến bởi máy chủ để 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 được tự động chia thành các khối. Đ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 HTML đó. Đ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 một trang. Mặc dù đây không phải là vấn đề về hiệu suất thời gian chạy (thay vào đó, đây là vấn đề về độ trễ mạng khi 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 bằng cách bỏ qua hoạt động tối ưu hoá hiệu suất cơ bản này của trình duyệt.
Những việc bạn có thể làm để giảm tác động của việc kết xuất phía máy khách đến hiệu suất
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 giá trị INP thấp trong dữ liệu thực tế, thì có thể bạn đang 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 những 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ì, bạn có thể tìm hiểu một số nguyên nhân tiềm ẩn sau đây để 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 đó, trình duyệt xử lý HTML từ máy chủ theo cách có hiệu suất rất cao theo mặc định. Thao tá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 thao tác 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 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 của mình. 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 sẽ yêu cầu và sẽ 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 để kết xuất HTML trên máy chủ. Tuy nhiên, hãy lưu ý rằng phương thức kết xuất phía máy chủ truyền thống sử dụng phương pháp đồng bộ, 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 phát trực tiếp cho Node.js hoặc các thời gian chạy JavaScript khác để máy chủ có thể bắt đầu truyền phát trực tiếp 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 kết xuất HTML trên máy chủ, Next.js cũng có thể tạo tĩnh HTML cho những trang không thay đổi dựa trên bối cảnh người dùng (chẳng hạn như xác thực).
- Vue cũng thực hiện kết xuất phía máy khách theo mặc định. Tuy nhiên, giống như React, Vue cũng có thể kết xuất HTML của 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 nếu có thể, hoặc cân nhắc mức độ trừu tượng cao hơn cho dự án Vue của bạn để dễ dàng triển khai các phương pháp hay nhất.
- Theo mặc định, Svelte kết xuất HTML trên máy chủ – mặc dù nếu mã thành phần của bạn cần truy cập vào các không gian tên dành riêng cho trình duyệt (ví dụ:
window
), thì bạn có thể không kết xuất được HTML của thành phần đó trên máy chủ. Khám phá các phương pháp thay thế bất cứ khi nào có thể để bạn không gây ra quá trình kết xuất không cần thiết ở phía máy khách. SvelteKit (tương tự như Next.js đối với React) nhúng nhiều phương pháp hay nhất vào các dự án Svelte của bạn, nhờ đó bạn có thể tránh được những cạm bẫy 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 có kích thước lớn, quá trình xử lý cần thiết để hiển thị các DOM này có xu hướng tăng lên. Cho dù trang web của bạn là một SPA hoàn chỉnh 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 đó nhỏ nhất có thể. Điều này sẽ giúp giảm lượng công việc cần thiết trong quá trình hiển thị phía máy khách để hiển thị HTML đó, hy vọng sẽ giúp duy trì chỉ số INP thấp hơn cho trang web của bạn.
Cân nhắc kiến trúc trình thực thi dịch vụ phát trực tuyến
Đây là một kỹ thuật nâng cao (có thể không dễ dàng áp dụng cho mọi trường hợp sử dụng), nhưng đây là kỹ thuật 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 chuyển từ trang này sang trang khác. Bạn có thể dùng trình chạy dịch vụ để lưu trước vào bộ nhớ đệm các phần tĩnh của trang web trong CacheStorage
trong khi dùng API ReadableStream
để tìm nạp phần còn lại của HTML của một trang từ máy chủ.
Khi sử dụng thành công kỹ thuật này, bạn sẽ 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 ấn tượng rằng 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ể trông gần giống như một SPA, nhưng không có những nhược điểm của việc kết xuất phía máy khách. Việc này cũng giảm lượng HTML mà bạn đang yêu cầu từ máy chủ.
Nói tóm lại, cấu trúc worker dịch vụ truyền phát trực tiếp không thay thế logic điều hướng tích hợp sẵn của trình duyệt mà bổ sung cho logic đó. Để biết thêm thông tin về cách đạt được điều này bằng Workbox, hãy đọc bài viết Ứng dụng nhiều trang nhanh hơn với các luồng.
Kết luận
Cách trang web của bạn nhận và hiển thị HTML sẽ ảnh hưở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 để 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à kết xuất gia tăng, đồng thời tự động nhường quyền cho 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 mà bạn có thể tránh được trong nhiều trường hợp. Tuy nhiên, do yêu cầu của từng trang web riêng lẻ, nên bạn không thể tránh hoàn toàn tình trạng này. Để giảm thiểu các tác vụ có thể mất nhiều thời gian do việc kết xuất quá nhiều phí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 nhỏ nhất có thể 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 cho máy khách, đồng thời tận dụng tính năng phân tích cú pháp gia tăng và kết xuất 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 tối đa quá trình hiển thị phía máy khách của trang web, bạn sẽ cải thiện không chỉ INP của trang web mà còn các chỉ số khác như LCP, TBT và thậm chí cả TTFB trong một số trường hợp.
Hình ảnh chính trên Unsplash, của Maik Jonietz.