Kích thước DOM lớn có tác động nhiều hơn đến khả năng tương tác so với bạn nghĩ. Hướng dẫn này giải thích lý do và những việc bạn có thể làm.
Không có cách nào khác: khi bạn tạo một trang web, trang đó sẽ có một Mô hình đối tượng tài liệu (DOM). DOM đại diện cho cấu trúc HTML trên trang của bạn, đồng thời cấp cho JavaScript và CSS quyền truy cập vào cấu trúc và nội dung của trang.
Tuy nhiên, vấn đề là kích thước của DOM ảnh hưởng đến khả năng của trình duyệt trong việc hiển thị trang một cách nhanh chóng và hiệu quả. Nói chung, DOM càng lớn thì càng tốn kém để hiển thị trang đó ban đầu và cập nhật chế độ hiển thị sau này trong vòng đời của trang.
Điều này sẽ trở thành vấn đề trên các trang có DOM rất lớn khi các tương tác sửa đổi hoặc cập nhật DOM kích hoạt công việc bố cục tốn kém ảnh hưởng đến khả năng phản hồi nhanh của trang. Công việc bố cục tốn kém có thể ảnh hưởng đến Lượt tương tác với nội dung hiển thị tiếp theo (INP) của một trang; Nếu bạn muốn một trang nhanh chóng phản hồi các lượt tương tác của người dùng, thì bạn phải đảm bảo rằng kích thước DOM của bạn chỉ đủ lớn khi cần.
Khi nào DOM của một trang quá lớn?
Theo Lighthouse, kích thước DOM của một trang vượt quá 1.400 nút. Lighthouse sẽ bắt đầu gửi cảnh báo khi DOM của trang vượt quá 800 nút. Lấy ví dụ về HTML sau:
<ul>
<li>List item one.</li>
<li>List item two.</li>
<li>List item three.</li>
</ul>
Trong mã trên, có bốn phần tử DOM: phần tử <ul>
và ba phần tử con <li>
. Trang web của bạn gần như chắc chắn sẽ có nhiều nút hơn thế này, vì vậy điều quan trọng là phải hiểu bạn có thể làm gì để kiểm soát kích thước DOM, cũng như các chiến lược khác để tối ưu hoá công việc hiển thị sau khi bạn nhận được DOM của trang nhỏ nhất có thể.
DOM lớn ảnh hưởng như thế nào đến hiệu suất trang?
DOM lớn ảnh hưởng đến hiệu suất của trang theo một số cách:
- Trong quá trình kết xuất ban đầu của trang. Khi CSS được áp dụng cho một trang, một cấu trúc tương tự như DOM được gọi là Mô hình đối tượng CSS (CSSOM) sẽ được tạo. Khi bộ chọn CSS tăng tính cụ thể, CSSOM trở nên phức tạp hơn và cần nhiều thời gian hơn để chạy bố cục, tạo kiểu, kết hợp và vẽ cần thiết để vẽ trang web lên màn hình. Công việc bổ sung này làm tăng độ trễ tương tác cho các lượt tương tác xảy ra sớm trong quá trình tải trang.
- Khi các lượt tương tác sửa đổi DOM, thông qua việc chèn hoặc xoá phần tử hoặc bằng cách sửa đổi nội dung và kiểu của DOM, công việc cần thiết để hiển thị bản cập nhật đó có thể dẫn đến việc bố cục, tạo kiểu, kết hợp và vẽ rất tốn kém. Giống như trường hợp kết xuất ban đầu của trang, việc tăng độ cụ thể của bộ chọn CSS có thể làm tăng công việc kết xuất khi các phần tử HTML được chèn vào DOM do kết quả của một lượt tương tác.
- Khi JavaScript truy vấn DOM, các tham chiếu đến các phần tử DOM được lưu trữ trong bộ nhớ. Ví dụ: nếu bạn gọi
document.querySelectorAll
để chọn tất cả các phần tử<div>
trên một trang, thì chi phí bộ nhớ có thể đáng kể nếu kết quả trả về nhiều phần tử DOM.
Tất cả những yếu tố này đều có thể ảnh hưởng đến khả năng tương tác, nhưng mục thứ hai trong danh sách trên đặc biệt quan trọng. Nếu một lượt tương tác dẫn đến thay đổi đối với DOM, thì có thể bắt đầu rất nhiều việc có thể góp phần vào INP kém trên trang.
Làm cách nào để đo lường kích thước DOM?
Bạn có thể đo kích thước DOM theo một số cách. Phương thức đầu tiên sử dụng Lighthouse. Khi bạn chạy quy trình kiểm tra, số liệu thống kê về DOM của trang hiện tại sẽ nằm trong quy trình kiểm tra "Tránh kích thước DOM quá lớn" trong tiêu đề "Chẩn đoán". Trong phần này, bạn có thể thấy tổng số phần tử DOM, phần tử DOM chứa nhiều phần tử con nhất, cũng như phần tử DOM sâu nhất.
Một phương thức đơn giản hơn là sử dụng bảng điều khiển JavaScript trong công cụ dành cho nhà phát triển trong bất kỳ trình duyệt lớn nào. Để biết tổng số phần tử HTML trong DOM, bạn có thể sử dụng mã sau trong bảng điều khiển sau khi trang tải xong:
document.querySelectorAll('*').length;
Nếu muốn xem nội dung cập nhật về kích thước DOM theo thời gian thực, bạn cũng có thể sử dụng công cụ theo dõi hiệu suất. Khi sử dụng công cụ này, bạn có thể liên hệ các thao tác bố cục và tạo kiểu (cùng với các khía cạnh hiệu suất khác) với kích thước DOM hiện tại.
Nếu kích thước DOM sắp đạt đến ngưỡng cảnh báo về kích thước DOM của Lighthouse hoặc không đạt được ngưỡng này, thì bước tiếp theo là tìm cách giảm kích thước DOM để cải thiện khả năng phản hồi các lượt tương tác của người dùng trên trang, nhờ đó cải thiện INP của trang web.
Làm cách nào để đo lường số lượng phần tử DOM chịu ảnh hưởng của một lượt tương tác?
Nếu đang lập hồ sơ một tương tác chậm trong phòng thí nghiệm mà bạn nghi ngờ có liên quan đến kích thước DOM của trang, bạn có thể tìm ra có bao nhiêu phần tử DOM bị ảnh hưởng bằng cách chọn bất kỳ phần hoạt động nào trong trình phân tích có nhãn "Tính toán lại Kiểu" và quan sát dữ liệu ngữ cảnh trong bảng điều khiển dưới cùng.
Trong ảnh chụp màn hình ở trên, hãy quan sát thấy việc tính toán lại kiểu của tác phẩm (khi được chọn) cho biết số lượng phần tử bị ảnh hưởng. Mặc dù ảnh chụp màn hình ở trên cho thấy một trường hợp nghiêm trọng về ảnh hưởng của kích thước DOM đến việc hiển thị hoạt động trên một trang có nhiều phần tử DOM, thông tin chẩn đoán này hữu ích trong mọi trường hợp để xác định xem kích thước của DOM có phải là yếu tố hạn chế trong thời gian khung tiếp theo hiển thị theo một tương tác hay không.
Làm cách nào để giảm kích thước DOM?
Ngoài việc kiểm tra HTML của trang web để tìm các mã đánh dấu không cần thiết, cách chính để giảm kích thước DOM là giảm độ sâu DOM. Một tín hiệu cho thấy DOM của bạn có thể sâu không cần thiết là khi bạn thấy mã đánh dấu trông giống như thế này trong thẻ Phần tử trong công cụ cho nhà phát triển của trình duyệt:
<div>
<div>
<div>
<div>
<!-- Contents -->
</div>
</div>
</div>
</div>
Khi thấy các mẫu như thế này, bạn có thể đơn giản hoá chúng bằng cách làm phẳng cấu trúc DOM. Việc này sẽ làm giảm số lượng phần tử DOM và có thể giúp bạn đơn giản hoá các kiểu trang.
Độ sâu DOM cũng có thể là một triệu chứng của các khung mà bạn sử dụng. Cụ thể, các khung dựa trên thành phần (chẳng hạn như các khung dựa trên JSX) yêu cầu bạn lồng nhiều thành phần trong một vùng chứa mẹ.
Tuy nhiên, có nhiều khung cho phép bạn tránh lồng ghép các thành phần bằng cách sử dụng cái gọi là mảnh. Các khung dựa trên thành phần cung cấp mảnh dưới dạng một tính năng bao gồm (nhưng không giới hạn ở) những khung sau:
Bằng cách sử dụng các mảnh trong khung mà bạn chọn, bạn có thể giảm chiều sâu DOM. Nếu lo ngại về tác động của cấu trúc DOM làm phẳng đối với việc tạo kiểu, bạn có thể hưởng lợi từ việc sử dụng các chế độ bố cục hiện đại hơn (và nhanh hơn) như flexbox hoặc grid.
Các chiến lược khác nên cân nhắc
Ngay cả khi bạn cố gắng làm phẳng cây DOM và xoá các phần tử HTML không cần thiết để giữ cho DOM nhỏ nhất có thể, DOM vẫn có thể khá lớn và kích hoạt nhiều công việc kết xuất khi thay đổi để phản hồi hoạt động tương tác của người dùng. Nếu gặp phải trường hợp này, bạn có thể cân nhắc một số chiến lược khác để hạn chế công việc kết xuất.
Cân nhắc phương pháp cộng gộp
Có thể người dùng không nhìn thấy phần lớn trang của bạn trong lần đầu hiển thị. Đây có thể là cơ hội để tải lười HTML bằng cách bỏ qua các phần đó của DOM khi khởi động, nhưng thêm các phần đó vào khi người dùng tương tác với các phần của trang yêu cầu các khía cạnh ẩn ban đầu của trang.
Phương pháp này hữu ích cả trong quá trình tải ban đầu và thậm chí là cả sau đó. Đối với lần tải trang ban đầu, bạn sẽ thực hiện trước ít công việc kết xuất hơn, có nghĩa là tải trọng HTML ban đầu của bạn sẽ nhẹ hơn và sẽ hiển thị nhanh hơn. Nhờ đó, các lượt tương tác trong giai đoạn quan trọng đó sẽ có nhiều cơ hội chạy hơn mà ít phải cạnh tranh hơn để thu hút sự chú ý của chuỗi chính.
Nếu ban đầu bạn có nhiều phần của trang bị ẩn khi tải, điều này cũng có thể tăng tốc các tương tác khác kích hoạt công việc hiển thị lại. Tuy nhiên, khi các hoạt động tương tác khác bổ sung nhiều hơn vào DOM, công việc hiển thị sẽ tăng lên khi DOM phát triển trong suốt vòng đời của trang.
Việc thêm vào DOM theo thời gian có thể khó khăn và có những đánh đổi riêng. Nếu chọn cách này, có thể bạn sẽ tạo các yêu cầu mạng để lấy dữ liệu nhằm điền sẵn HTML mà bạn định thêm vào trang để phản hồi tương tác của người dùng. Mặc dù các yêu cầu mạng đang bay không được tính vào INP, nhưng nó có thể làm tăng độ trễ dự kiến. Nếu có thể, hãy hiển thị vòng quay tải hoặc chỉ báo khác cho biết dữ liệu đang được tìm nạp để người dùng hiểu rằng có điều gì đó đang diễn ra.
Hạn chế độ phức tạp của bộ chọn CSS
Khi phân tích cú pháp các bộ chọn trong CSS, trình duyệt phải duyệt qua cây DOM để hiểu cách thức (và liệu có hay không) các bộ chọn đó áp dụng cho bố cục hiện tại. Các bộ chọn này càng phức tạp thì trình duyệt càng phải làm nhiều việc để thực hiện cả quá trình kết xuất ban đầu của trang, cũng như tăng cường tính năng tính toán lại kiểu và bố cục nếu trang thay đổi do một lượt tương tác.
Sử dụng thuộc tính content-visibility
CSS cung cấp thuộc tính content-visibility
. Đây là một cách hiệu quả để hiển thị từng phần các phần tử DOM ngoài màn hình. Khi các phần tử tiếp cận khung nhìn, chúng sẽ được hiển thị theo yêu cầu. Lợi ích của content-visibility
không chỉ loại bỏ một lượng đáng kể công việc kết xuất trong lần hiển thị trang ban đầu, mà còn bỏ qua công việc kết xuất đối với các phần tử ngoài màn hình khi DOM trang thay đổi do sự tương tác của người dùng.
Kết luận
Giảm kích thước DOM của bạn chỉ còn những gì thực sự cần thiết là một cách hay để tối ưu hoá INP của trang web của bạn. Nhờ vậy, bạn có thể giảm lượng thời gian mà trình duyệt cần để thực hiện công việc bố cục và kết xuất khi DOM được cập nhật. Ngay cả khi bạn không thể giảm đáng kể kích thước DOM, có một số kỹ thuật bạn có thể sử dụng để tách riêng công việc kết xuất với cây con DOM, chẳng hạn như vùng chứa CSS và thuộc tính CSS content-visibility
.
Tuy nhiên, bạn thực hiện việc này bằng cách tạo một môi trường trong đó công việc kết xuất được giảm thiểu — cũng như giảm khối lượng công việc kết xuất mà trang của bạn thực hiện để phản hồi tương tác — kết quả là trang web của bạn sẽ cảm thấy phản hồi nhanh hơn cho người dùng khi họ tương tác với chúng. Điều đó có nghĩa là trang web của bạn sẽ có INP thấp hơn, đồng nghĩa với việc mang lại trải nghiệm tốt hơn cho người dùng.