Trước đây, việc đo lường tốc độ tải và hiển thị của người dùng đối với nội dung chính của trang web là một thách thức đối với các nhà phát triển web. Các chỉ số cũ như load hoặc DOMContentLoaded không hoạt động tốt vì chúng không nhất thiết tương ứng với những gì người dùng nhìn thấy trên màn hình. Ngoài ra, các chỉ số mới hơn về hiệu suất tập trung vào người dùng như Nội dung đầu tiên hiển thị (FCP) chỉ ghi lại giai đoạn đầu của trải nghiệm tải. Nếu một trang hiển thị màn hình chờ hoặc chỉ báo đang tải thì thời điểm này hiện không liên quan lắm cho người dùng.
Trước đây, chúng tôi đề xuất các chỉ số về hiệu suất như Nội dung hiển thị đầu tiên (FMP) và Chỉ số tốc độ (SI) (cả hai đều có trong Lighthouse) để giúp ghi lại thêm trải nghiệm tải sau lần hiển thị ban đầu. Tuy nhiên, những chỉ số này phức tạp, khó giải thích và thường không chính xác — nghĩa là chúng vẫn chưa xác định được thời điểm nội dung chính của trang được tải.
Dựa trên các cuộc thảo luận trong Nhóm công tác về hiệu suất web W3C và nghiên cứu tại Google, chúng tôi nhận thấy rằng cách chính xác hơn để đo lường thời điểm tải nội dung chính của trang là xem thời điểm phần tử lớn nhất được hiển thị.
LCP là gì?
LCP báo cáo thời gian kết xuất của khối văn bản hoặc hình ảnh lớn nhất hiển thị trong khung nhìn, so với thời điểm người dùng lần đầu chuyển đến trang.
Điểm LCP tốt là gì?
Để cung cấp trải nghiệm tốt cho người dùng, các trang web nên cố gắng có Thời gian hiển thị nội dung lớn nhất trong vòng 2,5 giây. Để đảm bảo hầu hết người dùng của bạn đạt được mục tiêu này, ngưỡng phù hợp để đo lường là phân vị thứ 75 của lượt tải trang, được phân đoạn trên thiết bị di động và thiết bị máy tính.
Những yếu tố nào được xem xét?
Như hiện được chỉ định trong Nội dung lớn nhất hiển thị API, các loại phần tử được xem xét cho Nội dung lớn nhất hiển thị là:
- Các phần tử
<img>
(thời gian trình chiếu khung hình đầu tiên được dùng cho nội dung động như GIF hoặc PNG động) - Phần tử
<image>
bên trong phần tử<svg>
- Các phần tử
<video>
(thời gian tải hình ảnh áp phích hoặc thời gian trình chiếu khung hình đầu tiên cho video được sử dụng (tuỳ theo thời gian nào đến trước) - Một phần tử có hình nền được tải bằng cách sử dụng hàm
url()
, (trái ngược với tính năng chuyển màu của CSS) - Các phần tử cấp khối chứa các nút văn bản hoặc các phần tử con của phần tử văn bản cấp cùng dòng.
Xin lưu ý rằng việc giới hạn các phần tử trong nhóm giới hạn này là có chủ ý để giữ mọi thứ đơn giản ngay từ đầu. Các yếu tố bổ sung (như khả năng hỗ trợ đầy đủ của <svg>
) có thể được thêm vào trong tương lai khi chúng tôi tiến hành thêm nghiên cứu.
Bên cạnh việc chỉ xem xét một số phần tử, các phép đo LCP sử dụng phương pháp phỏng đoán để loại trừ một số phần tử nhất định mà người dùng có thể sẽ thấy là "không có nội dung". Đối với các trình duyệt dựa trên Chromium, các trình duyệt này bao gồm:
- Các phần tử có độ mờ bằng 0 mà người dùng không nhìn thấy
- Các phần tử bao phủ toàn bộ khung nhìn, có thể được coi là nền chứ không phải nội dung
- Hình ảnh giữ chỗ hoặc các hình ảnh khác có entropy thấp có thể không phản ánh đúng nội dung của trang
Các trình duyệt có thể sẽ tiếp tục cải thiện những suy đoán này để đảm bảo chúng tôi đáp ứng được kỳ vọng của người dùng về phần tử có nội dung lớn nhất là gì.
Những quảng cáo "nội dung" này phương pháp phỏng đoán có thể khác với phương pháp mà hiển thị nội dung đầu tiên (FCP) sử dụng, có thể xem xét một số phần tử trong số này, chẳng hạn như hình ảnh phần giữ chỗ hoặc hình ảnh toàn khung nhìn, ngay cả khi chúng không đủ điều kiện là ứng cử viên LCP. Mặc dù cả hai đều sử dụng từ "nội dung" có tên, mục tiêu của các chỉ số này sẽ khác nhau. FCP đo lường khi bất kỳ nội dung nào được hiển thị lên màn hình và LCP khi nội dung chính được hiển thị sao cho LCP được có ý định lựa chọn nhiều hơn.
Kích thước của một phần tử được xác định như thế nào?
Kích thước của phần tử được báo cáo cho LCP thường là kích thước mà người dùng nhìn thấy trong khung nhìn. Nếu phần tử mở rộng bên ngoài khung nhìn hoặc nếu bất kỳ phần tử nào bị cắt bớt hoặc có phần tràn không nhìn thấy, thì các phần đó sẽ không được tính vào kích thước của phần tử.
Đối với các thành phần hình ảnh đã được đổi kích thước so với kích thước nội tại, thì kích thước được báo cáo sẽ là kích thước hiển thị hoặc kích thước nội tại, tuỳ theo kích thước nào nhỏ hơn.
Đối với các phần tử văn bản, LCP chỉ xem xét hình chữ nhật nhỏ nhất có thể chứa tất cả các nút văn bản.
Đối với tất cả phần tử, LCP không tính đến lề, khoảng đệm hoặc đường viền được áp dụng thông qua CSS.
LCP được báo cáo khi nào?
Các trang web thường tải theo giai đoạn và do đó, phần tử lớn nhất trên trang có thể thay đổi.
Để xử lý khả năng thay đổi này, trình duyệt sẽ gửi một PerformanceEntry
thuộc loại largest-contentful-paint
xác định phần tử có nội dung lớn nhất ngay khi trình duyệt vẽ khung đầu tiên. Tuy nhiên, sau khi kết xuất các khung tiếp theo, phương thức này sẽ gửi một PerformanceEntry
khác bất cứ khi nào phần tử có nội dung lớn nhất thay đổi.
Ví dụ: trên một trang có văn bản và hình ảnh chính, ban đầu trình duyệt có thể chỉ hiển thị văn bản. Lúc đó, trình duyệt sẽ gửi một mục nhập largest-contentful-paint
có thuộc tính element
có thể tham chiếu đến <p>
hoặc <h1>
. Sau đó, khi hình ảnh chính tải xong, mục largest-contentful-paint
thứ hai sẽ được gửi đi và thuộc tính element
của mục đó sẽ tham chiếu đến <img>
.
Một phần tử chỉ có thể được coi là phần tử có nội dung lớn nhất sau khi phần tử đó đã kết xuất và hiển thị cho người dùng. Những hình ảnh chưa tải sẽ không được coi là "hiển thị". Cả các nút văn bản đều không sử dụng phông chữ web trong khoảng thời gian chặn phông chữ. Trong những trường hợp như vậy, một phần tử nhỏ hơn có thể được báo cáo là phần tử có nội dung lớn nhất, nhưng ngay khi phần tử lớn hơn kết xuất xong, một PerformanceEntry
khác sẽ được tạo.
Ngoài hình ảnh và phông chữ tải muộn, một trang có thể thêm các phần tử mới vào DOM khi có nội dung mới. Nếu bất kỳ phần tử mới nào trong số này lớn hơn phần tử nội dung lớn nhất trước đó, thì PerformanceEntry
mới cũng sẽ được báo cáo.
Nếu phần tử có nội dung lớn nhất bị xoá khỏi khung nhìn hoặc thậm chí khỏi DOM, thì phần tử đó vẫn là phần tử có nội dung lớn nhất trừ phi phần tử lớn hơn được hiển thị.
Trình duyệt sẽ ngừng báo cáo các mục nhập mới ngay khi người dùng tương tác với trang (qua thao tác nhấn, cuộn hoặc nhấn phím), vì tương tác của người dùng thường thay đổi nội dung hiển thị cho người dùng (đặc biệt đúng với thao tác cuộn).
Để phân tích, bạn chỉ nên báo cáo PerformanceEntry
được gửi gần đây nhất đến dịch vụ phân tích của mình.
Thời gian tải so với thời gian kết xuất
Vì lý do bảo mật, dấu thời gian kết xuất của hình ảnh sẽ không hiển thị đối với những hình ảnh có nhiều nguồn gốc không có tiêu đề Timing-Allow-Origin
. Thay vào đó, chỉ thời gian tải của chúng được hiển thị (vì điều này đã được hiển thị thông qua nhiều API web khác).
Điều này có thể dẫn đến tình huống dường như không thể xảy ra, trong đó LCP được API web báo cáo là sớm hơn FCP. Trường hợp này không đúng nhưng chỉ xuất hiện do hạn chế bảo mật này.
Khi có thể, bạn nên đặt tiêu đề Timing-Allow-Origin
để các chỉ số của bạn chính xác hơn.
Các thay đổi về kích thước và bố cục của phần tử được xử lý như thế nào?
Để duy trì chi phí hiệu suất khi tính toán và gửi các mục nhập hiệu suất mới ở mức thấp, việc thay đổi kích thước hoặc vị trí của một phần tử sẽ không tạo ra các ứng viên LCP mới. Chỉ kích thước và vị trí ban đầu của phần tử trong khung nhìn mới được xem xét.
Điều này có nghĩa là hình ảnh ban đầu được kết xuất ngoài màn hình rồi sau đó chuyển đổi trên màn hình có thể không được báo cáo. Điều này cũng có nghĩa là các phần tử ban đầu được hiển thị trong khung nhìn nhưng sau đó bị đẩy xuống, ra khỏi khung nhìn vẫn sẽ báo cáo kích thước ban đầu trong khung nhìn.
Ví dụ
Dưới đây là một số ví dụ về thời điểm Nội dung lớn nhất xuất hiện trên một số trang web phổ biến:
![Dòng thời gian Nội dung lớn nhất hiển thị trên cnn.com](https://web.dev/static/articles/lcp/image/largest-contentful-paint-fc43128e011aa.png?authuser=5&hl=vi)
![Dòng thời gian của Nội dung lớn nhất hiển thị trên Techcrunch.com](https://web.dev/static/articles/lcp/image/largest-contentful-paint-3713e2f14970a.png?authuser=5&hl=vi)
Trong cả hai tiến trình trên, phần tử lớn nhất sẽ thay đổi khi nội dung tải. Trong ví dụ đầu tiên, nội dung mới được thêm vào DOM và làm thay đổi phần tử nào lớn nhất. Trong ví dụ thứ hai, các thay đổi về bố cục và nội dung trước đó là lớn nhất sẽ bị xoá khỏi khung nhìn.
Mặc dù nội dung tải trễ thường lớn hơn nội dung đã có trên trang, nhưng điều đó chưa chắc đúng. Hai ví dụ tiếp theo cho thấy LCP xảy ra trước khi trang được tải hoàn toàn.
![Dòng thời gian Nội dung lớn nhất hiển thị trên instagram.com](https://web.dev/static/articles/lcp/image/largest-contentful-paint-9bc403e812154.png?authuser=5&hl=vi)
![Dòng thời gian Nội dung lớn nhất hiển thị trên google.com](https://web.dev/static/articles/lcp/image/largest-contentful-paint-6c5554de0eac7.png?authuser=5&hl=vi)
Trong ví dụ đầu tiên, biểu trưng Instagram được tải tương đối sớm và vẫn là thành phần lớn nhất ngay cả khi các nội dung khác xuất hiện dần. Trong ví dụ về trang kết quả của Google Tìm kiếm, phần tử lớn nhất là một đoạn văn bản được hiển thị trước khi bất kỳ hình ảnh hoặc biểu trưng nào tải xong. Vì tất cả các hình ảnh riêng lẻ đều nhỏ hơn đoạn này, nên đoạn văn bản vẫn là phần tử lớn nhất trong suốt quá trình tải.
Cách đo lường LCP
LCP có thể được đo lường trong phòng thí nghiệm hoặc tại thực địa và có sẵn trong các công cụ sau:
Công cụ tại hiện trường
- Báo cáo trải nghiệm người dùng trên Chrome
- PageSpeed Insights
- Search Console (báo cáo Chỉ số quan trọng chính của trang web)
- Thư viện JavaScript
web-vitals
Công cụ cho phòng thí nghiệm
Đo lường LCP trong JavaScript
Để đo lường LCP trong JavaScript, bạn có thể sử dụng API Nội dung lớn nhất hiển thị. Ví dụ sau cho biết cách tạo PerformanceObserver
để theo dõi các mục nhập largest-contentful-paint
và ghi nhật ký các mục đó vào bảng điều khiển.
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry);
}
}).observe({type: 'largest-contentful-paint', buffered: true});
Trong ví dụ trên, mỗi mục nhập largest-contentful-paint
được ghi lại đại diện cho ứng viên LCP hiện tại. Nhìn chung, giá trị startTime
của mục nhập cuối cùng được phát ra là giá trị LCP. Tuy nhiên, điều đó không phải lúc nào cũng đúng. Không phải mục nhập largest-contentful-paint
nào cũng hợp lệ để đo lường LCP.
Phần sau đây liệt kê sự khác biệt giữa nội dung API báo cáo và cách tính chỉ số.
Sự khác biệt giữa chỉ số và API
- API sẽ gửi mục nhập
largest-contentful-paint
cho các trang được tải trong thẻ nền, nhưng các trang đó sẽ bị bỏ qua khi tính LCP. - API sẽ tiếp tục gửi các mục nhập
largest-contentful-paint
sau khi trang đã chạy ở chế độ nền, nhưng các mục nhập đó sẽ được bỏ qua khi tính toán LCP (các phần tử chỉ có thể được xem xét nếu trang đã chạy ở nền trước trong toàn bộ thời gian). - API không báo cáo các mục nhập
largest-contentful-paint
khi trang được khôi phục từ bộ nhớ đệm cho thao tác tiến/lùi, nhưng LCP sẽ được đo lường trong những trường hợp này vì người dùng trải nghiệm chúng dưới dạng lượt truy cập trang riêng biệt. - API không xem xét các phần tử trong iframe nhưng chỉ số này hoạt động như một phần của trải nghiệm người dùng trên trang. Trong các trang có LCP trong iframe (ví dụ: hình ảnh áp phích trên video được nhúng), điều này sẽ hiển thị dưới dạng sự khác biệt giữa CrUX và RUM. Để đo lường LCP một cách chính xác, bạn nên cân nhắc các yếu tố này. Khung phụ có thể dùng API để báo cáo các mục nhập
largest-contentful-paint
với khung mẹ để tổng hợp. - API đo lường LCP từ khi bắt đầu điều hướng, nhưng đối với các trang được kết xuất trước, LCP phải được đo từ
activationStart
vì thời gian này tương ứng với thời gian LCP mà người dùng đã trải nghiệm.
Thay vì ghi nhớ tất cả những khác biệt nhỏ này, nhà phát triển có thể sử dụng thư viện JavaScript web-vitals
để đo lường LCP. Thư viện này giúp xử lý những khác biệt này cho bạn (nếu có thể – lưu ý rằng vấn đề về iframe không được đề cập):
import {onLCP} from 'web-vitals';
// Measure and log LCP as soon as it's available.
onLCP(console.log);
Hãy tham khảo mã nguồn của onLCP()
để xem ví dụ đầy đủ về cách đo lường LCP trong JavaScript.
Điều gì sẽ xảy ra nếu phần tử lớn nhất không phải là phần tử quan trọng nhất?
Trong một số trường hợp, phần tử (hoặc các phần tử) quan trọng nhất trên trang không giống với phần tử lớn nhất và nhà phát triển có thể quan tâm đến việc đo lường thời gian hiển thị của các phần tử khác này thay thế. Bạn có thể thực hiện việc này bằng cách sử dụng API Thời gian phần tử, như mô tả trong bài viết về chỉ số tuỳ chỉnh.
Cách cải thiện LCP
Bạn có thể tham khảo hướng dẫn đầy đủ về cách tối ưu hoá LCP để biết quy trình xác định thời gian LCP trong lĩnh vực này và sử dụng dữ liệu của phòng thí nghiệm để xem chi tiết và tối ưu hoá các chỉ số này.
Tài nguyên khác
- Bài học rút ra từ việc giám sát hiệu suất trong Chrome của Annie Sullivan tại performance.now() (2019)
Nhật ký thay đổi
Đôi khi, lỗi được phát hiện trong các API dùng để đo lường chỉ số và đôi khi trong định nghĩa của chính các chỉ số đó. Do đó, đôi khi bạn cần phải thực hiện thay đổi và những thay đổi này có thể xuất hiện dưới dạng sự cải thiện hoặc hồi quy trong báo cáo nội bộ và trang tổng quan.
Để giúp bạn quản lý việc này, tất cả các thay đổi đối với cách triển khai hoặc định nghĩa của các chỉ số này sẽ xuất hiện trong Nhật ký thay đổi này.
Nếu muốn gửi ý kiến phản hồi về các chỉ số này, bạn có thể gửi ý kiến phản hồi trong nhóm Google phản hồi web-vitals-feedback.