Trước đây, các nhà phát triển web gặp khó khăn trong việc đo lường tốc độ tải và hiển thị nội dung chính của trang web cho người dùng. Các chỉ số cũ như load hoặc DOMContentLoaded không hoạt động hiệu quả vì các chỉ số này không nhất thiết phải tương ứng với nội dung mà người dùng nhìn thấy trên màn hình. Ngoài ra, các chỉ số hiệu suất mới hơn, lấy người dùng làm trung tâm như Thời gian hiển thị nội dung đầu tiên (FCP) chỉ ghi lại thời điểm bắt đầu 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ì khoảnh khắc này không liên quan lắm đến người dùng.
Trước đây, chúng tôi đã đề xuất các chỉ số hiệu suất như Nội dung đầu tiên hiển thị có ý nghĩa (FMP) và Chỉ số tốc độ (SI) (cả hai đều có trong Lighthouse) để giúp ghi lại nhiều trải nghiệm tải hơn sau lần sơn đầu tiên. Tuy nhiên, các 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 không xác định được thời điểm nội dung chính của trang tải xong.
Dựa trên các cuộc thảo luận trong Nhóm làm việc về hiệu suất web của W3C và nghiên cứu được thực hiện 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 nội dung chính của trang được tải là xem xét 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 hình ảnh, khối văn bản hoặc video lớn nhất xuất hiện trong khung nhìn, so với thời điểm người dùng truy cập vào trang lần đầu tiên.
Điểm LCP tốt là bao nhiêu?
Để đem lại trải nghiệm tốt cho người dùng, các trang web nên cố gắng đạt được điểm số Nội dung lớn nhất hiển thị là 2,5 giây trở xuống. Để đảm bảo bạn đang đạt được mục tiêu này cho hầu hết người dùng, ngưỡng phù hợp để đo lường là phân vị thứ 75 của số lượt tải trang, được phân đoạn trên thiết bị di động và máy tính.
Những phần tử nào được xem xét?
Như hiện được chỉ định trong API Thời gian hiển thị nội dung lớn nhất, các loại phần tử được xem xét cho Thời gian hiển thị nội dung lớn nhất là:
- Phần tử
<img>
(thời gian hiển thị khung đầu tiên được dùng cho nội dung động như GIF hoặc PNG động) - Các 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 hiển thị khung hình đầu tiên cho video được sử dụng – tuỳ theo thời gian nào đến sớm hơn) - Một phần tử có hình nền được tải bằng hàm
url()
, (thay vì dải màu 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 văn bản cấp nội tuyến khác.
Xin lưu ý rằng việc giới hạn các phần tử trong tập hợp hạn chế này là có chủ ý để giữ cho mọi thứ đơn giản ngay từ đầu. Các phần tử bổ sung (chẳng hạn như hỗ trợ đầy đủ <svg>
) có thể được thêm vào trong tương lai khi chúng tôi tiến hành nghiên cứu thêm.
Ngoài việc chỉ xem xét một số phần tử, các phép đo LCP còn sử dụng phương pháp phỏng đoán để loại trừ một số phần tử mà người dùng có thể coi là "không có nội dung". Đối với các trình duyệt dựa trên Chromium, những trình duyệt này bao gồm:
- Các phần tử có độ mờ bằng 0, không hiển thị với người dùng
- Các phần tử bao phủ toàn bộ khung nhìn, có thể được coi là nền thay vì nội dung
- Hình ảnh giữ chỗ hoặc hình ảnh khác có độ hỗn loạn thấp, có thể không phản ánh đúng nội dung của trang
Các trình duyệt có thể tiếp tục cải thiện các phương pháp phỏng đ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.
Các phương pháp phỏng đoán "có nội dung" này có thể khác với các phương pháp phỏng đoán mà Hiển thị nội dung đầu tiên (FCP) sử dụng. FCP 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 các phần tử đó không đủ điều kiện để trở thành đề xuất LCP. Mặc dù cả hai đều có từ "contentful" (có nội dung) trong tên, nhưng mục đích của các chỉ số này lại khác nhau. FCP đo lường thời điểm bất kỳ nội dung nào được vẽ lên màn hình và LCP khi nội dung chính được vẽ lên màn hình. Vì vậy, LCP có ý định chọn lọc 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 ra 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 hiển thị, thì các phần đó không được tính vào kích thước của phần tử.
Đối với các phần tử hình ảnh đã được đổi kích thước từ kích thước nội tại, kích thước được báo cáo 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ả các phần tử, LCP không xem xét lề, khoảng đệm hoặc đường viền được áp dụng bằng CSS.
Khi nào LCP được báo cáo?
Các trang web thường tải theo từng giai đoạn, 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 hình tiếp theo, lớp này sẽ gửi một PerformanceEntry
khác bất cứ khi nào phần tử 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. Tại thời điểm này, trình duyệt sẽ gửi một mục 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ột mục nhập largest-contentful-paint
thứ hai sẽ được gửi và thuộc tính element
của mục nhập đó sẽ tham chiếu đến <img>
.
Một phần tử chỉ có thể được coi là phần tử nội dung lớn nhất sau khi phần tử đó hiển thị và người dùng có thể nhìn thấy. Những hình ảnh chưa tải sẽ không được coi là "đã kết xuất". Các nút văn bản cũng không sử dụng phông chữ web trong 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 thúc quá trình kết xuất, 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ử có 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ử nội dung lớn nhất bị xoá khỏi khung nhìn hoặc thậm chí là khỏi DOM, thì phần tử đó vẫn là phần tử nội dung lớn nhất, trừ phi một 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 (thông qua thao tác nhấn, cuộn hoặc nhấn phím), vì hoạt động tương tác của người dùng thường thay đổi nội dung hiển thị với người dùng (đặc biệt là khi cuộn).
Đối với mục đích phân tích, bạn chỉ nên báo cáo PerformanceEntry
được gửi gần đây nhất cho dịch vụ phân tích.
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 hình ảnh trên nhiều nguồn gốc thiếu tiêu đề Timing-Allow-Origin
. Thay vào đó, chỉ thời gian tải của các thành phần hiển thị này mới được hiển thị (vì thông tin 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 các API web báo cáo sớm hơn FCP. Tuy nhiên, điều này không phải là trường hợp thực tế mà chỉ là do quy định hạn chế bảo mật này.
Bạn nên luôn đặt tiêu đề Timing-Allow-Origin
khi có thể để các chỉ số của bạn chính xác hơn.
Làm cách nào để xử lý các thay đổi về bố cục và kích thước phần tử?
Để giảm thiểu hao tổn hiệu suất khi tính toán và gửi các mục hiệu suất mới, những thay đổi về kích thước hoặc vị trí của một phần tử sẽ không tạo ra các đề xuất LCP mới. Chỉ xem xét kích thước và vị trí ban đầu của phần tử trong khung nhìn.
Điều này có nghĩa là những hình ảnh ban đầu được kết xuất ngoài màn hình rồi 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 kết xuất trong khung nhìn, sau đó bị đẩy xuống, nằm ngoài khung nhìn sẽ vẫn báo cáo kích thước ban đầu trong khung nhìn.
Ví dụ
Sau đây là một số ví dụ về thời điểm xảy ra Thời gian hiển thị nội dung lớn nhất trên một số trang web phổ biến:
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à thay đổi phần tử nào lớn nhất. Trong ví dụ thứ hai, bố cục thay đổi và nội dung trước đây lớn nhất sẽ bị xoá khỏi khung nhìn.
Mặc dù thường thì nội dung tải muộn lớn hơn nội dung đã có trên trang, nhưng không phải lúc nào cũng vậy. Hai ví dụ tiếp theo cho thấy LCP xảy ra trước khi trang tải xong.
Trong ví dụ đầu tiên, biểu trưng Instagram được tải tương đối sớm và vẫn là phần tử lớn nhất ngay cả khi nội dung khác hiển thị dần dần. Trong ví dụ về trang kết quả trên Google Tìm kiếm, phần tử lớn nhất là một đoạn văn bản xuất hiện trước khi hình ảnh hoặc biểu trưng nào đó tải xong. Vì tất cả hình ảnh riêng lẻ đều nhỏ hơn đoạn văn này, nên đoạn văn này vẫn là phần tử lớn nhất trong suốt quá trình tải.
Cách đo lường LCP
Bạn có thể đo lường LCP trong phòng thí nghiệm hoặc trực tiếp tại hiện trường. LCP cũng có 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ụ của Labs
Đo lường LCP trong JavaScript
Để đo lường LCP trong JavaScript, bạn có thể sử dụng Largest Contentful Paint API (API Thời gian hiển thị nội dung lớn nhất). Ví dụ sau đây cho biết cách tạo PerformanceObserver
để theo dõi các mục nhập largest-contentful-paint
và ghi lại các mục nhập đó 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 largest-contentful-paint
được ghi lại đại diện cho đề xuất 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, không phải lúc nào cũng vậy. 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 mà API báo cáo và cách tính chỉ số này.
Sự khác biệt giữa chỉ số và API
- API sẽ gửi các mục nhập
largest-contentful-paint
cho các trang được tải trong thẻ nền, nhưng bạn nên bỏ qua các trang đó khi tính toán LCP. - API sẽ tiếp tục gửi các mục nhập
largest-contentful-paint
sau khi một trang chạy ở chế độ nền, nhưng các mục nhập đó sẽ bị bỏ qua khi tính LCP (các phần tử chỉ có thể được xem xét nếu trang chạy ở chế độ 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 quay lại/chuyển tiếp, nhưng bạn nên đo lường LCP trong những trường hợp này vì người dùng sẽ trải nghiệm các 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 lại xem xét vì các phần tử đó là một phần của trải nghiệm người dùng trên trang. Trong các trang có LCP trong một 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 chính xác LCP, bạn nên cân nhắc những yếu tố này. Khung con có thể sử dụng API để báo cáo các mục nhập
largest-contentful-paint
của chúng cho 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, bạn nên đo lường LCP từ
activationStart
vì thời điểm đó 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 điểm 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 sẽ xử lý những điểm 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()
để biết 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à các nhà phát triển có thể quan tâm hơn đến việc đo lường thời gian kết xuất của các phần tử khác này. Bạn có thể thực hiện việc này bằng cách sử dụng Element Timing API (API Thời gian của phần tử), như mô tả trong bài viết về chỉ số tuỳ chỉnh.
Cách cải thiện LCP
Chúng tôi có hướng dẫn đầy đủ về cách tối ưu hoá LCP để hướng dẫn bạn thực hiện quy trình xác định thời gian LCP trong thực tế và sử dụng dữ liệu trong phòng thí nghiệm để xem chi tiết và tối ưu hoá thời gian đó.
Tài nguyên khác
- Bài học rút ra từ việc theo dõi hiệu suất trong Chrome của Annie Sullivan tại performance.now() (2019)
Nhật ký thay đổi
Đôi khi, chúng tôi phát hiện lỗi trong các API dùng để đo lường chỉ số và đôi khi là trong định nghĩa của chính các chỉ số đó. Do đó, đôi khi bạn phải thực hiện các thay đổi và những thay đổi này có thể xuất hiện dưới dạng điểm cải thiện hoặc hồi quy trong các báo cáo và trang tổng quan nội bộ.
Để giúp bạn quản lý việc này, tất cả thay đổi đối với việc 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 có ý kiến phản hồi về các chỉ số này, bạn có thể gửi ý kiến đó trong nhóm Google web-vitals-feedback.