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 của trang và 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 trở thành vấn đề trong các trang có DOM rất lớn khi các hoạt động 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 đến nội dung hiển thị tiếp theo (INP) của trang; Nếu bạn muốn trang phản hồi nhanh các hoạt động tương tác của người dùng, điều quan trọng là phải đảm bảo kích thước DOM chỉ lớn khi cần thiết.
Khi nào DOM của một trang quá lớn?
Theo Lighthouse, kích thước DOM của một trang là quá lớn khi vượt quá 1.400 nút. Lighthouse sẽ bắt đầu đưa ra cảnh báo khi DOM của một 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ó 4 phần tử DOM: phần tử <ul>
và 3 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à bạn phải hiểu những việc bạn có thể làm để 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 kết xuất sau khi bạn đã thu nhỏ DOM của trang đến mức tối đa.
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 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 đối với các lượt tương tác xảy ra sớm trong quá trình tải trang.
- Khi các hoạt động 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 DOM, công việc cần thiết để hiển thị nội dung cập nhật đó có thể dẫn đến việc bố cục, tạo kiểu, kết hợp và vẽ 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 tệp tham chiếu đến phần tử DOM sẽ được lưu trữ trong bộ nhớ. Ví dụ: nếu bạn gọi
document.querySelectorAll
để chọn tất 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ề một số lượng lớn 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ì điều này có thể kích hoạt nhiều công việc có thể góp phần làm giảm INP trên một trang.
Làm cách nào để đo lường kích thước DOM?
Bạn có thể đo lường 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 kết 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 phân tích một lượ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 hiểu số lượng phần tử DOM bị ảnh hưởng bằng cách chọn bất kỳ 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 theo 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 cực đoan về ảnh hưởng của kích thước DOM đối với công việc kết xuất trên một trang có nhiều phần tử DOM, nhưng 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ố giới hạn thời gian cần thiết để khung tiếp theo vẽ để phản hồi một lượ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ể quá sâu là nếu bạn thấy mã đánh dấu có dạng như sau trong thẻ Elements (Phần tử) của công cụ dành 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á các mẫu đó 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, nhiều khung cho phép bạn tránh lồng các thành phần bằng cách sử dụng các 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 việc làm phẳng cấu trúc DOM đố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 cầ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à có thể cả sau đó. Đối với lần tải trang ban đầu, bạn sẽ thực hiện ít công việc kết xuất hơn trước, nghĩa là tải trọng HTML ban đầu sẽ nhẹ hơn và kết xuất nhanh hơn. Điều này sẽ giúp các lượt tương tác trong khoảng thời gian quan trọng đó có nhiều cơ hội chạy hơn mà ít cạnh tranh hơn cho sự chú ý của luồng chính.
Nếu ban đầu bạn ẩn nhiều phần của trang khi tải, thì việc này cũng có thể tăng tốc các hoạt động tương tác khác kích hoạt quá trình kết xuất lại. Tuy nhiên, khi các hoạt động tương tác khác thêm vào DOM, công việc kết xuất 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, bạn có thể 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 dự định thêm vào trang để phản hồi hoạt động tương tác của người dùng. Mặc dù các yêu cầu mạng đang diễn ra không được tính vào INP, nhưng chúng có thể làm tăng độ trễ nhận thấy được. 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ến đến khung nhìn, chúng sẽ được kết xuất theo yêu cầu. Lợi ích của content-visibility
không chỉ cắt giảm đáng kể lượng công việc kết xuất trên lượt kết xuất trang ban đầu, mà còn bỏ qua công việc kết xuất cho các phần tử ngoài màn hình khi DOM trang thay đổi do tương tác của người dùng.
Kết luận
Việc giảm kích thước DOM chỉ còn những phần thực sự cần thiết là một cách hay để tối ưu hoá INP của trang web. Bằng cách này, bạn có thể giảm thời gian trình duyệt 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 không thể giảm đáng kể kích thước DOM, bạn vẫn có thể sử dụng một số kỹ thuật để tách riêng công việc kết xuất thành một cây con DOM, chẳng hạn như tính năng chứa CSS và thuộc tính CSS content-visibility
.
Tuy nhiên, việc 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 lượng công việc kết xuất mà trang của bạn thực hiện để phản hồi các lượt tương tác – sẽ giúp trang web của bạn phản hồi người dùng nhanh hơn khi họ tương tác với trang web. Điều đó có nghĩa là trang web của bạn sẽ có INP thấp hơn, từ đó mang lại trải nghiệm tốt hơn cho người dùng.