Hướng dẫn từng bước về cách phân tích LCP và xác định các khía cạnh chính cần cải thiện.
Nội dung lớn nhất hiển thị (LCP) là một trong ba chỉ số thuộc Các chỉ số quan trọng về trang web. Chỉ số này thể hiện tốc độ tải nội dung chính của một trang web. Cụ thể, LCP đo lường thời gian từ khi người dùng bắt đầu tải trang cho đến khi hình ảnh hoặc khối văn bản lớn nhất hiển thị trong khung nhìn.
Để cung cấp trải nghiệm tốt cho người dùng, các trang web nên cố gắng đạt LCP từ 2,5 giây trở xuống trong ít nhất 75% lượt truy cập trang.
Một số yếu tố có thể ảnh hưởng đến tốc độ tải và hiển thị trang web của trình duyệt và sự chậm trễ trên bất kỳ yếu tố nào cũng có thể có tác động đáng kể đến LCP.
Rất hiếm khi việc sửa nhanh một phần của trang lại giúp cải thiện đáng kể LCP. Để cải thiện LCP, bạn phải xem xét toàn bộ quá trình tải và đảm bảo rằng mọi bước trong quá trình này đều được tối ưu hoá.
Tìm hiểu về chỉ số LCP (Nội dung lớn nhất hiển thị)
Trước khi tối ưu hoá LCP, nhà phát triển cần tìm hiểu xem liệu họ có gặp vấn đề nào về LCP hay không và mức độ của bất kỳ vấn đề nào như vậy.
LCP có thể được đo lường bằng một số công cụ và không phải tất cả các công cụ này đều đo lường LCP theo cùng một cách. Để hiểu LCP của người dùng thực, chúng ta nên xem xét trải nghiệm của người dùng thực, thay vì những gì một công cụ dựa trên phòng thí nghiệm như Lighthouse hoặc kiểm thử cục bộ cho thấy gì. Những công cụ dùng trong phòng thí nghiệm này có thể cung cấp rất nhiều thông tin để giải thích và giúp bạn cải thiện LCP. Tuy nhiên, xin lưu ý rằng nếu chỉ thử nghiệm trong phòng thí nghiệm thì chưa thể phản ánh hoàn toàn trải nghiệm thực tế của người dùng.
Dữ liệu LCP dựa trên người dùng thực có thể hiển thị từ các công cụ Giám sát người dùng thực (RUM) được cài đặt trên một trang web hoặc bằng cách sử dụng Báo cáo trải nghiệm người dùng trên Chrome (CrUX) – một báo cáo thu thập dữ liệu ẩn danh của người dùng Chrome thực cho hàng triệu trang web.
Sử dụng dữ liệu LCP CrUX của PageSpeed Insights
PageSpeed Insights cung cấp quyền truy cập vào dữ liệu CrUX ở phần trên cùng có nhãn Khám phá trải nghiệm của người dùng thực sự. Dữ liệu chi tiết hơn dựa trên phòng thí nghiệm có trong phần dưới cùng có tên Chẩn đoán các vấn đề về hiệu suất. Nếu bạn có dữ liệu CrUX cho trang web của mình, thì trước tiên, hãy luôn tập trung vào dữ liệu của người dùng thực.
![Dữ liệu CrUX xuất hiện trong PageSpeed Insights](https://web.developers.google.cn/static/articles/optimize-lcp/image/pagespeed-insights-crux-updated.png?authuser=5&hl=vi)
Thông tin chi tiết về tốc độ trang hiển thị tối đa 4 dữ liệu CrUX khác nhau:
- Dữ liệu di động cho URL này
- Dữ liệu trên máy tính cho URL này
- Dữ liệu di động cho toàn bộ Origin (Nguồn gốc)
- Dữ liệu Máy tính cho toàn bộ Gốc
Bạn có thể bật/tắt các tính năng này trong phần điều khiển ở trên cùng và trên cùng bên phải của mục này. Nếu một URL không có đủ dữ liệu để hiển thị ở cấp URL nhưng có dữ liệu cho máy chủ gốc, thì PageSpeed Insights sẽ luôn hiển thị dữ liệu gốc.
![PageSpeed Insights sẽ quay lại dữ liệu cấp độ gốc khi không có dữ liệu cấp url](https://web.developers.google.cn/static/articles/optimize-lcp/image/url-level-data-unavailable.png?authuser=5&hl=vi)
LCP cho toàn bộ nguồn gốc có thể rất khác so với LCP của một trang riêng lẻ, tuỳ thuộc vào cách LCP được tải trên trang đó so với các trang khác trên nguồn gốc đó. Điểm cũng có thể bị ảnh hưởng bởi cách khách truy cập điều hướng đến các trang này. Trang chủ có xu hướng được người dùng mới truy cập và vì vậy thường có thể được tải "lạnh", không có bất kỳ nội dung nào được lưu vào bộ nhớ đệm và do đó thường là trang có tốc độ chậm nhất trên trang web.
Bằng cách xem xét 4 danh mục dữ liệu CrUX, bạn có thể hiểu rõ liệu vấn đề LCP là chỉ xảy ra trên trang này hay là vấn đề chung chung hơn trên toàn trang web. Tương tự, công cụ này có thể cho biết những loại thiết bị nào gặp vấn đề về LCP.
Sử dụng các chỉ số bổ sung của PageSpeed Insights CrUX
Những nhà quảng cáo tìm cách tối ưu hoá LCP cũng nên sử dụng các thời điểm Thời gian hiển thị nội dung đầu tiên (FCP) và Thời gian xuất hiện byte đầu tiên (TTFB). Đây là những chỉ số chẩn đoán hữu ích có thể cung cấp thông tin chi tiết có giá trị về LCP.
TTFB là thời gian khi khách truy cập bắt đầu điều hướng đến một trang (ví dụ: nhấp vào một liên kết), cho đến khi nhận được byte đầu tiên của tài liệu HTML. Một TTFB cao có thể khiến việc đạt được LCP 2, 5 giây trở nên khó khăn hoặc thậm chí là không thể.
TTFB cao có thể do nhiều lần chuyển hướng máy chủ, khách truy cập ở xa máy chủ trang web gần nhất, khách truy cập ở điều kiện mạng kém hoặc không thể sử dụng nội dung được lưu vào bộ nhớ đệm do tham số truy vấn.
Khi một trang bắt đầu hiển thị, có thể là lớp hiển thị ban đầu (ví dụ: màu nền), tiếp theo là một số nội dung xuất hiện (ví dụ: tiêu đề trang web). Sự xuất hiện của nội dung ban đầu được đo lường bằng FCP. Mức chênh lệch giữa FCP và các chỉ số khác có thể rất rõ ràng.
Sự chênh lệch lớn giữa TTFB và FCP có thể cho biết trình duyệt cần tải nhiều tài sản chặn hiển thị xuống. Đây cũng có thể là dấu hiệu cho thấy trang web phải hoàn thành nhiều công sức để hiển thị bất kỳ nội dung có ý nghĩa nào — dấu hiệu cổ điển cho thấy một trang web phụ thuộc nhiều vào khả năng hiển thị phía máy khách.
Sự chênh lệch lớn giữa FCP và LCP cho biết tài nguyên LCP không có sẵn ngay để trình duyệt ưu tiên (ví dụ: văn bản hoặc hình ảnh do JavaScript quản lý thay vì có trong HTML ban đầu), hoặc trình duyệt đang hoàn tất công việc khác trước khi có thể hiển thị nội dung LCP.
Sử dụng dữ liệu của PageSpeed Insights Lighthouse
Mục Lighthouse của PageSpeed Insights sẽ đưa ra một số hướng dẫn để cải thiện LCP. Tuy nhiên, trước tiên, bạn nên kiểm tra xem LCP được cung cấp có phù hợp với dữ liệu người dùng thực do CrUX cung cấp hay không. Nếu Lighthouse và CrUX không đồng ý với nhau, thì CrUX có thể cung cấp thông tin chính xác hơn về trải nghiệm người dùng của bạn. Hãy đảm bảo dữ liệu CrUX là dành cho trang của bạn chứ không phải toàn bộ nguồn gốc, trước khi bạn hành động đối với trang đó.
Nếu cả Lighthouse và CrUX đều cho thấy những giá trị LCP cần cải thiện, thì phần Lighthouse có thể cung cấp hướng dẫn có giá trị về cách cải thiện LCP. Sử dụng bộ lọc LCP để chỉ hiển thị các lượt kiểm tra liên quan đến LCP như sau:
![Cơ hội và thông tin chẩn đoán về LCP của Lighthouse](https://web.developers.google.cn/static/articles/optimize-lcp/image/psi-lighthouse-lcp-opportunities.png?authuser=5&hl=vi)
Bên cạnh các Cơ hội để cải thiện, còn có thông tin Chẩn đoán có thể cung cấp thêm thông tin để giúp chẩn đoán vấn đề. Công cụ chẩn đoán Phần tử Nội dung lớn nhất hiển thị hiển thị bảng phân tích hữu ích về các thời gian khác nhau tạo nên LCP:
![Các giai đoạn LCP trong Lighthouse](https://web.developers.google.cn/static/articles/optimize-lcp/image/lighthouse-lcp-phases.png?authuser=5&hl=vi)
Chúng ta sẽ tìm hiểu sâu hơn về các phần phụ này trong phần tiếp theo.
Phân tích LCP
Tối ưu hoá LCP có thể là một nhiệm vụ phức tạp hơn khi PageSpeed Insights không trả lời được cho bạn cách cải thiện chỉ số này. Đối với các công việc phức tạp, bạn nên chia nhỏ thành các nhiệm vụ nhỏ hơn, dễ quản lý hơn và giải quyết từng nhiệm vụ riêng biệt.
Phần này trình bày phương pháp chia nhỏ LCP thành các phần phụ quan trọng nhất, sau đó trình bày các đề xuất cụ thể và các phương pháp hay nhất về cách tối ưu hoá từng phần.
Hầu hết các lượt tải trang thường bao gồm một số yêu cầu mạng, nhưng để xác định cơ hội cải thiện LCP, bạn nên bắt đầu bằng cách chỉ xem hai yêu cầu sau:
- Tài liệu HTML ban đầu
- Tài nguyên LCP (nếu có)
Mặc dù các yêu cầu khác trên trang có thể ảnh hưởng đến LCP, nhưng hai yêu cầu này – cụ thể là thời điểm tài nguyên LCP bắt đầu và kết thúc – cho biết trang của bạn có được tối ưu hoá cho LCP hay không.
Để xác định tài nguyên LCP, bạn có thể dùng các công cụ cho nhà phát triển (chẳng hạn như PageSpeed Insights được thảo luận trước đó, Công cụ của Chrome cho nhà phát triển hoặc WebPageTest) để xác định phần tử LCP. Từ đó, bạn có thể so khớp URL (một lần nữa, nếu có) do phần tử tải trên một thác nước mạng của tất cả tài nguyên do trang tải.
Ví dụ: hình ảnh trực quan sau đây cho thấy những tài nguyên này được làm nổi bật trên biểu đồ thác nước mạng từ một lượt tải trang thông thường, trong đó phần tử LCP cần một yêu cầu hình ảnh để hiển thị.
![Thác nước trên mạng, trong đó tài nguyên HTML và LCP được làm nổi bật](https://web.developers.google.cn/static/articles/optimize-lcp/image/a-network-waterfall-the-919387402b1d3.png?authuser=5&hl=vi)
Để có một trang được tối ưu hoá hiệu quả, bạn muốn yêu cầu tài nguyên LCP bắt đầu tải sớm nhất có thể và bạn muốn phần tử LCP kết xuất nhanh nhất có thể sau khi tài nguyên LCP tải xong. Để giúp hình dung liệu một trang cụ thể có tuân thủ nguyên tắc này hay không, bạn có thể chia nhỏ tổng thời gian LCP thành các phần phụ sau:
- Thời gian cho byte đầu tiên (TTFB)
- Khoảng thời gian từ khi người dùng bắt đầu tải trang cho đến khi trình duyệt nhận byte đầu tiên của phản hồi tài liệu HTML.
- Độ trễ khi tải tài nguyên
- Khoảng thời gian từ lúc TTFB đến khi trình duyệt bắt đầu tải tài nguyên LCP. Nếu phần tử LCP không yêu cầu tải tài nguyên để kết xuất (ví dụ: nếu là một nút văn bản được hiển thị bằng phông chữ hệ thống), thời gian này là 0.
- Thời lượng tải tài nguyên
- Khoảng thời gian cần thiết để tải chính tài nguyên LCP. Nếu LCP (Nội dung lớn nhất hiển thị) không yêu cầu tải tài nguyên để kết xuất, thời gian này là 0.
- Độ trễ hiển thị phần tử
- Khoảng thời gian từ khi tài nguyên LCP tải xong cho đến khi phần tử LCP kết xuất đầy đủ.
LCP của mỗi trang bao gồm bốn danh mục con. Không có khoảng trống hoặc chồng chéo giữa chúng và chúng cộng lại thành toàn bộ thời gian LCP.
![Bản phân tích về LCP hiển thị 4 danh mục phụ](https://web.developers.google.cn/static/articles/optimize-lcp/image/lcp-breakdown-four-categories.png?authuser=5&hl=vi)
Mỗi trang có thể chia giá trị LCP thành bốn phần phụ. Không có sự chồng chéo hay khoảng cách giữa các chỉ số này. Các cấp độ này cộng lại thành toàn bộ thời gian LCP.
Khi tối ưu hoá LCP, bạn nên cố gắng tối ưu hoá từng phần phụ này. Nhưng một điều quan trọng cần lưu ý là bạn cần phải tối ưu hoá tất cả các yếu tố đó. Trong một số trường hợp, việc tối ưu hoá áp dụng cho một phần sẽ không cải thiện LCP mà chỉ chuyển thời gian đã lưu sang phần khác.
Ví dụ: trong thác nước mạng trước đó, nếu bạn giảm kích thước tệp của hình ảnh bằng cách nén nhiều hơn hoặc chuyển sang định dạng tối ưu hơn (chẳng hạn như AVIF hoặc WebP), thì điều đó sẽ làm giảm thời lượng tải tài nguyên, nhưng thực sự sẽ không cải thiện LCP vì thời gian sẽ chỉ chuyển sang phần phụ độ trễ hiển thị phần tử:
![Bảng phân tích tương tự về LCP được trình bày trước đó, trong đó danh mục phụ thời lượng tải tài nguyên được rút ngắn nhưng tổng thời gian LCP sẽ không thay đổi.](https://web.developers.google.cn/static/articles/optimize-lcp/image/the-same-lcp-breakdown-render-delay.png?authuser=5&hl=vi)
Lý do điều này xảy ra là do trên trang này, phần tử LCP bị ẩn cho đến khi mã JavaScript tải xong, sau đó mọi thứ sẽ hiển thị cùng một lúc.
Ví dụ này giúp minh hoạ điểm cần tối ưu hoá tất cả các phần phụ này để đạt được kết quả LCP tốt nhất.
Thời gian cho phần phụ tối ưu
Để tối ưu hoá từng phần phụ của LCP, bạn cần hiểu rõ cách phân tích lý tưởng của các phần phụ này trên một trang được tối ưu hoá hiệu quả.
Trong 4 phần phụ, có 2 phần có từ "delay" (trì hoãn) trong tên của chúng. Đây là một dấu hiệu cho thấy bạn muốn đưa những thời điểm này về càng gần 0 nhất có thể. Hai phần còn lại liên quan đến các yêu cầu mạng về bản chất sẽ tốn thời gian.
Xin lưu ý rằng các bảng chi tiết theo thời gian này là hướng dẫn chứ không phải là quy tắc nghiêm ngặt. Nếu thời gian LCP trên các trang của bạn đều nằm trong khoảng 2,5 giây, thì tỷ lệ tương đối không còn quan trọng nữa. Nhưng nếu bạn đang dành nhiều thời gian không cần thiết vào một trong hai "sự chậm trễ" thì sẽ rất khó để liên tục đạt mục tiêu 2, 5 giây.
Một cách hay để phân tích thời gian LCP là:
- Phần lớn thời gian của LCP sẽ được dành cho việc tải tài liệu HTML và nguồn LCP.
- Bất kỳ lúc nào trước LCP mà một trong 2 tài nguyên này không tải được là cơ hội để cải thiện.
Cách tối ưu hoá từng phần
Bây giờ, bạn đã hiểu cách từng thời gian của phần phụ LCP được phân tích trên một trang được tối ưu hoá tốt, bạn có thể bắt đầu tối ưu hoá các trang của mình.
Bốn phần tiếp theo sẽ trình bày các đề xuất và phương pháp hay nhất về cách tối ưu hoá từng phần. Các đề xuất được trình bày theo thứ tự, bắt đầu từ những phương án tối ưu hoá có khả năng tạo ra tác động lớn nhất.
1. Loại bỏ độ trễ tải tài nguyên
Mục tiêu trong bước này là đảm bảo tài nguyên LCP bắt đầu tải càng sớm càng tốt. Mặc dù về lý thuyết, tài nguyên có thể bắt đầu tải sớm nhất là ngay sau TTFB, nhưng trên thực tế, luôn có độ trễ trước khi trình duyệt thực sự bắt đầu tải tài nguyên.
Nguyên tắc chung là tài nguyên LCP của bạn phải bắt đầu tải cùng lúc với tài nguyên đầu tiên được tải bởi trang đó. Hay nói cách khác, nếu tài nguyên LCP bắt đầu tải muộn hơn tài nguyên đầu tiên thì bạn sẽ có cơ hội cải thiện.
![Biểu đồ thác nước trên mạng cho thấy tài nguyên LCP bắt đầu sau tài nguyên đầu tiên, cho thấy cơ hội cải thiện](https://web.developers.google.cn/static/articles/optimize-lcp/image/a-network-waterfall-diagr-1ee19fc20ee1f.png?authuser=5&hl=vi)
Nói chung, có 2 yếu tố ảnh hưởng đến tốc độ tải tài nguyên LCP:
- Khi tài nguyên được khám phá.
- Mức độ ưu tiên của tài nguyên.
Tối ưu hoá khi người dùng tìm thấy tài nguyên
Để đảm bảo tài nguyên LCP của bạn bắt đầu tải sớm nhất có thể, bạn cần phải tìm thấy tài nguyên trong phản hồi ban đầu của tài liệu HTML bằng trình quét tải trước của trình duyệt. Ví dụ: trong các trường hợp sau, trình duyệt có thể phát hiện tài nguyên LCP bằng cách quét nội dung phản hồi của tài liệu HTML:
- Phần tử LCP là một phần tử
<img>
và các thuộc tínhsrc
hoặcsrcset
của phần tử này có trong mã đánh dấu HTML ban đầu. - Phần tử LCP đòi hỏi hình nền CSS, nhưng hình ảnh đó được tải trước bằng
<link rel="preload">
trong mã đánh dấu HTML (hoặc dùng một tiêu đềLink
). - Phần tử LCP là một nút văn bản cần có phông chữ trên web để hiển thị và phông chữ này được tải bằng
<link rel="preload">
trong mã đánh dấu HTML (hoặc tiêu đềLink
).
Sau đây là một số ví dụ trong đó không thể tìm thấy tài nguyên LCP khi quét phản hồi của tài liệu HTML:
- Phần tử LCP là
<img>
được tự động thêm vào trang bằng JavaScript. - Phần tử LCP được tải từng phần bằng một thư viện JavaScript để ẩn các thuộc tính
src
hoặcsrcset
của phần tử đó (thường làdata-src
hoặcdata-srcset
). - Phần tử LCP yêu cầu hình nền CSS.
Trong mỗi trường hợp như vậy, trình duyệt cần phải chạy tập lệnh hoặc áp dụng biểu định kiểu (thường liên quan đến việc chờ yêu cầu mạng kết thúc) trước khi có thể phát hiện tài nguyên LCP và có thể bắt đầu tải tài nguyên đó. Điều này không bao giờ là tối ưu.
Để loại bỏ độ trễ tải tài nguyên không cần thiết, tài nguyên LCP của bạn phải có thể tìm thấy được từ nguồn HTML. Trong trường hợp tài nguyên chỉ được tham chiếu từ một tệp CSS hoặc JavaScript bên ngoài, tài nguyên LCP phải được tải trước với mức độ ưu tiên tìm nạp cao, ví dụ:
<!-- Load the stylesheet that will reference the LCP image. -->
<link rel="stylesheet" href="/path/to/styles.css">
<!-- Preload the LCP image with a high fetchpriority so it starts loading with the stylesheet. -->
<link rel="preload" fetchpriority="high" as="image" href="/path/to/hero-image.webp" type="image/webp">
Tối ưu hoá mức độ ưu tiên cho tài nguyên
Ngay cả khi tài nguyên LCP có thể tìm thấy qua mã đánh dấu HTML, tài nguyên này vẫn có thể không bắt đầu tải sớm như tài nguyên đầu tiên. Điều này có thể xảy ra nếu trình duyệt tải trước suy đoán mức độ ưu tiên của trình quét không nhận ra rằng tài nguyên là quan trọng hoặc nếu trình duyệt xác định rằng các tài nguyên khác quan trọng hơn.
Ví dụ: bạn có thể trì hoãn hình ảnh LCP bằng cách sử dụng HTML nếu đặt loading="lazy"
trên phần tử <img>
. Khi sử dụng tính năng tải từng phần, tài nguyên sẽ không được tải cho đến khi bố cục xác nhận hình ảnh đang nằm trong khung nhìn, do đó có thể bắt đầu tải muộn hơn so với bình thường.
Ngay cả khi không tải từng phần, hình ảnh ban đầu vẫn không được tải với mức độ ưu tiên cao nhất bởi các trình duyệt vì chúng không phải là tài nguyên chặn hiển thị. Bạn có thể gợi ý cho trình duyệt biết tài nguyên nào quan trọng nhất bằng cách sử dụng thuộc tính fetchpriority
cho những tài nguyên có thể hưởng lợi khi có mức độ ưu tiên cao hơn:
<img fetchpriority="high" src="/path/to/hero-image.webp">
Bạn nên đặt fetchpriority="high"
trên phần tử <img>
nếu cho rằng đó có thể là phần tử LCP của trang. Tuy nhiên, việc đặt mức độ ưu tiên cao cho nhiều hơn một hoặc hai hình ảnh sẽ khiến chế độ cài đặt mức độ ưu tiên không hữu ích trong việc giảm LCP.
Bạn cũng có thể giảm mức độ ưu tiên của những hình ảnh có thể xuất hiện ở đầu phản hồi tài liệu nhưng không hiển thị do cách định kiểu, chẳng hạn như hình ảnh trong trang trình bày băng chuyền không hiển thị khi khởi động:
<img fetchpriority="low" src="/path/to/carousel-slide-3.webp">
Việc giảm mức độ ưu tiên một số tài nguyên có thể giúp tăng băng thông cho những tài nguyên cần nhiều hơn, nhưng hãy cẩn thận. Luôn kiểm tra mức độ ưu tiên tài nguyên trong Công cụ cho nhà phát triển và kiểm thử các thay đổi bằng công cụ trong phòng thí nghiệm và tại hiện trường.
Sau khi bạn tối ưu hoá mức độ ưu tiên và thời gian khám phá tài nguyên LCP, thác nước trên mạng của bạn sẽ có dạng như sau (với tài nguyên LCP bắt đầu cùng lúc với tài nguyên đầu tiên):
![Sơ đồ thác nước trên mạng cho thấy tài nguyên LCP hiện bắt đầu cùng lúc với tài nguyên đầu tiên](https://web.developers.google.cn/static/articles/optimize-lcp/image/a-network-waterfall-diagr-b6906b9fce22.png?authuser=5&hl=vi)
2. Loại bỏ độ trễ hiển thị phần tử
Mục tiêu trong bước này là đảm bảo phần tử LCP có thể hiển thị ngay lập tức sau khi tài nguyên tải xong, bất kể việc đó xảy ra vào thời điểm nào.
Lý do chính khiến phần tử LCP không thể hiển thị ngay sau khi tài nguyên của phần tử này tải xong là nếu quá trình kết xuất bị chặn vì một số lý do khác:
- Tính năng hiển thị toàn bộ trang sẽ bị chặn do biểu định kiểu hoặc tập lệnh đồng bộ trong
<head>
vẫn đang tải. - Tài nguyên LCP đã tải xong, nhưng phần tử LCP chưa được thêm vào DOM (đang chờ một số mã JavaScript tải).
- Phần tử đang bị ẩn bởi một số mã khác, chẳng hạn như thư viện thử nghiệm A/B vẫn đang xác định thử nghiệm nào người dùng sẽ tham gia.
- Luồng chính bị chặn do các tác vụ mất nhiều thời gian, và thao tác kết xuất cần phải đợi cho đến khi các tác vụ mất nhiều thời gian đó hoàn tất.
Các phần sau giải thích cách giải quyết các nguyên nhân thường gặp nhất gây ra độ trễ hiển thị phần tử không cần thiết.
Giảm hoặc nội tuyến biểu định kiểu chặn hiển thị
Biểu định kiểu được tải từ đánh dấu HTML sẽ chặn hiển thị tất cả nội dung tuân theo các biểu định kiểu đó. Điều này tốt, vì bạn thường sẽ không muốn hiển thị HTML không được định kiểu. Tuy nhiên, nếu biểu định kiểu quá lớn đến mức mất nhiều thời gian tải hơn đáng kể so với tài nguyên LCP, thì bảng tính sẽ ngăn phần tử LCP hiển thị – ngay cả sau khi tài nguyên của biểu mẫu tải xong, như trong ví dụ sau:
![Biểu đồ thác nước trên mạng cho thấy một tệp CSS lớn chặn quá trình kết xuất phần tử LCP vì mất nhiều thời gian tải hơn tài nguyên LCP](https://web.developers.google.cn/static/articles/optimize-lcp/image/a-network-waterfall-diagr-42b740846d30d.png?authuser=5&hl=vi)
Để khắc phục vấn đề này, bạn có các lựa chọn như sau:
- chèn biểu định kiểu vào HTML để tránh việc yêu cầu thêm mạng; hoặc
- giảm kích thước của biểu định kiểu.
Nói chung, bạn chỉ nên đặt cùng dòng cho biểu định kiểu nếu biểu định kiểu của bạn có kích thước nhỏ do nội dung cùng dòng trong HTML không thể hưởng lợi từ việc lưu vào bộ nhớ đệm trong những lần tải trang tiếp theo. Nếu biểu định kiểu quá lớn đến mức mất nhiều thời gian tải hơn tài nguyên LCP, thì biểu định kiểu đó sẽ không phù hợp để sử dụng cùng dòng.
Trong hầu hết các trường hợp, cách tốt nhất để đảm bảo biểu định kiểu không chặn hiển thị phần tử LCP là giảm kích thước của phần tử đó để phần tử đó nhỏ hơn tài nguyên LCP. Điều này giúp đảm bảo đây không phải là điểm tắc nghẽn của hầu hết các lượt truy cập.
Một số đề xuất giúp giảm kích thước của biểu định kiểu là:
- Xoá CSS không dùng đến: sử dụng Công cụ của Chrome cho nhà phát triển để tìm các quy tắc CSS không dùng đến và có khả năng bị xoá (hoặc trì hoãn).
- Trì hoãn CSS không quan trọng: chia biểu định kiểu của bạn thành các kiểu cần thiết cho lần tải trang đầu tiên, sau đó là các kiểu có thể tải từng phần.
- Rút gọn và nén CSS: đối với các kiểu quan trọng, hãy đảm bảo bạn giảm kích thước chuyển của các kiểu đó nhiều nhất có thể.
Hoãn hoặc chặn JavaScript chặn hiển thị cùng dòng
Bạn hầu như không cần phải thêm các tập lệnh đồng bộ (tập lệnh không có thuộc tính async
hoặc defer
) vào <head>
của các trang vì việc này hầu như sẽ luôn có tác động tiêu cực đến hiệu suất.
Trong trường hợp mã JavaScript cần chạy càng sớm càng tốt trong khi tải trang, tốt nhất là nên chèn mã đó vào cùng dòng để việc hiển thị không bị trì hoãn khi chờ một yêu cầu mạng khác. Tuy nhiên, giống như biểu định kiểu, bạn chỉ nên tập lệnh cùng dòng nếu chúng rất nhỏ.
<head> <script src="/path/to/main.js"></script> </head>
<head> <script> // Inline script contents directly in the HTML. // IMPORTANT: only do this for very small scripts. </script> </head>
Sử dụng tính năng hiển thị phía máy chủ
Hiển thị phía máy chủ (SSR) là quá trình chạy logic ứng dụng phía máy khách trên máy chủ và phản hồi các yêu cầu tài liệu HTML bằng mã đánh dấu HTML đầy đủ.
Từ góc độ tối ưu hoá LCP, có 2 lợi thế chính của SSR:
- Bạn có thể tìm thấy tài nguyên hình ảnh của mình từ nguồn HTML (như đã thảo luận trong bước 1 trước đó).
- Nội dung trang của bạn sẽ không yêu cầu yêu cầu JavaScript bổ sung để hoàn tất trước khi có thể hiển thị.
Nhược điểm chính của SSR là cần thêm thời gian xử lý của máy chủ, do đó có thể làm chậm TTFB của bạn. Tuy nhiên, sự đánh đổi này thường đáng giá vì thời gian xử lý của máy chủ nằm trong tầm kiểm soát của bạn, trong khi khả năng của mạng và thiết bị của người dùng thì không.
Một tuỳ chọn tương tự như SSR được gọi là tạo trang web tĩnh (SSG) hoặc kết xuất trước. Đây là quá trình tạo các trang HTML trong một bước xây dựng thay vì theo yêu cầu. Nếu có thể kết xuất trước với kiến trúc của bạn, thường đó là lựa chọn tốt hơn để đạt được hiệu suất.
Chia nhỏ những việc cần làm dài
Ngay cả khi bạn đã làm theo lời khuyên trước đó và mã JavaScript của bạn không chặn hiển thị cũng như không chịu trách nhiệm hiển thị các phần tử của bạn, mã này vẫn có thể trì hoãn LCP.
Lý do phổ biến nhất khiến điều này xảy ra là khi các trang tải các tệp JavaScript lớn, cần được phân tích cú pháp và thực thi trên luồng chính của trình duyệt. Tức là ngay cả khi tài nguyên hình ảnh đã được tải xuống hoàn toàn, có thể tài nguyên hình ảnh đó vẫn phải đợi cho đến khi tập lệnh không liên quan thực thi xong trước khi có thể kết xuất.
Hiện nay, tất cả trình duyệt đều hiển thị hình ảnh trên luồng chính. Điều này có nghĩa là bất kỳ nội dung nào chặn luồng chính cũng đều có thể dẫn đến độ trễ hiển thị thành phần không cần thiết.
3. Giảm thời lượng tải tài nguyên
Mục tiêu của bước này là giảm thời gian chuyển các byte của tài nguyên qua mạng đến thiết bị của người dùng. Nhìn chung, có 3 cách để làm việc đó:
- Giảm kích thước của tài nguyên.
- Giảm khoảng cách mà tài nguyên phải di chuyển.
- Giảm tranh chấp về băng thông mạng.
- Loại bỏ hoàn toàn thời gian kết nối mạng.
Giảm kích thước của tài nguyên
Tài nguyên LCP của một trang (nếu có) sẽ là một hình ảnh hoặc một phông chữ trên web. Các hướng dẫn sau đây trình bày chi tiết về cách giảm kích thước của cả hai:
- Phân phát kích thước hình ảnh tối ưu
- Dùng định dạng hình ảnh hiện đại
- Nén hình ảnh
- Giảm cỡ chữ trên web
Giảm quãng đường tài nguyên phải di chuyển
Ngoài việc giảm kích thước của tài nguyên, bạn cũng có thể giảm thời gian tải bằng cách đặt máy chủ của bạn càng gần người dùng về mặt địa lý càng tốt. Cách tốt nhất để làm điều đó là sử dụng mạng phân phối nội dung (CDN).
CDN hình ảnh đặc biệt hữu ích vì chúng không chỉ làm giảm khoảng cách mà tài nguyên phải di chuyển mà còn giảm kích thước của tài nguyên — tự động triển khai tất cả các đề xuất giảm kích thước trước đó cho bạn.
Giảm tranh chấp về băng thông mạng
Ngay cả khi bạn đã giảm kích thước của tài nguyên và khoảng cách phải di chuyển, tài nguyên vẫn có thể mất nhiều thời gian để tải nếu bạn tải nhiều tài nguyên khác cùng lúc. Vấn đề này được gọi là tranh chấp mạng.
Nếu bạn đã cấp cao fetchpriority
cho tài nguyên LCP và bắt đầu tải tài nguyên đó càng sớm càng tốt thì trình duyệt sẽ cố gắng hết sức để ngăn tài nguyên có mức độ ưu tiên thấp hơn cạnh tranh với nó. Tuy nhiên, nếu bạn đang tải nhiều tài nguyên có fetchpriority
cao hoặc nếu bạn chỉ tải nhiều tài nguyên nói chung thì điều đó có thể ảnh hưởng đến tốc độ tải tài nguyên LCP.
Loại bỏ hoàn toàn thời gian kết nối mạng
Cách tốt nhất để giảm thời lượng tải tài nguyên là loại bỏ mạng hoàn toàn khỏi quy trình. Nếu bạn phân phát tài nguyên của mình theo chính sách kiểm soát bộ nhớ đệm hiệu quả thì những khách truy cập yêu cầu các tài nguyên đó lần thứ hai sẽ được phân phát chúng từ bộ nhớ đệm – khiến thời lượng tải tài nguyên về cơ bản là bằng 0!
Nếu tài nguyên LCP là một phông chữ trên web, thì ngoài việc giảm kích thước phông chữ trên web, bạn cũng nên cân nhắc xem có cần chặn việc hiển thị trong quá trình tải tài nguyên phông chữ trên web hay không. Nếu bạn thiết lập giá trị font-display
không phải là auto
hoặc block
, thì văn bản sẽ luôn hiển thị trong quá trình tải và LCP sẽ không bị chặn trong một yêu cầu mạng bổ sung.
Cuối cùng, nếu tài nguyên LCP nhỏ, bạn nên đặt các tài nguyên này vào cùng dòng dưới dạng một URL dữ liệu. Việc này cũng sẽ loại bỏ các yêu cầu mạng bổ sung. Tuy nhiên, việc sử dụng URL dữ liệu đi kèm với cảnh báo vì khi đó tài nguyên không thể được lưu vào bộ nhớ đệm và trong một số trường hợp có thể dẫn đến độ trễ hiển thị lâu hơn do chi phí giải mã tăng thêm.
4. Giảm thời gian đến byte đầu tiên
Mục tiêu của bước này là phân phối HTML ban đầu càng nhanh càng tốt. Bước này được liệt kê cuối cùng vì đây thường là bước mà nhà phát triển có ít quyền kiểm soát nhất. Tuy nhiên, đây cũng là một trong những bước quan trọng nhất vì nó ảnh hưởng trực tiếp đến từng bước sau đó. Không có gì có thể xảy ra trên giao diện người dùng cho đến khi chương trình phụ trợ phân phối byte nội dung đầu tiên đó, vì vậy, bất kỳ điều gì bạn có thể làm để tăng tốc TTFB của mình cũng sẽ cải thiện mọi chỉ số tải khác.
Một nguyên nhân phổ biến khiến TTFB chậm đối với một trang web khác có tốc độ nhanh là khách truy cập đến thông qua nhiều lượt chuyển hướng, chẳng hạn như qua quảng cáo hoặc đường liên kết được rút ngắn. Luôn giảm thiểu số lần chuyển hướng mà khách truy cập phải chờ.
Một nguyên nhân phổ biến khác là không thể dùng nội dung đã lưu vào bộ nhớ đệm từ máy chủ cạnh của CDN và tất cả các yêu cầu phải được chuyển hướng ngược về máy chủ gốc. Điều này có thể xảy ra nếu khách truy cập sử dụng thông số URL riêng biệt cho mục đích phân tích – ngay cả khi các thông số này không tạo ra các trang khác nhau.
Để xem hướng dẫn cụ thể về cách tối ưu hoá TTFB, hãy tham khảo hướng dẫn tối ưu hoá TTFB.
Theo dõi bảng chi tiết về LCP trong JavaScript
Bạn có thể xem thông tin về thời gian của tất cả các phần phụ LCP được thảo luận trước đó trong JavaScript thông qua việc kết hợp các API hiệu suất sau đây:
Lợi ích của việc tính toán các giá trị thời gian này trong JavaScript là bạn có thể gửi các giá trị đó đến nhà cung cấp phân tích hoặc ghi chúng vào công cụ cho nhà phát triển của bạn để giúp gỡ lỗi và tối ưu hoá.
Ví dụ: ảnh chụp màn hình sau đây sử dụng phương thức performance.measure()
từ API Thời gian người dùng để thêm các thanh vào kênh Thời gian trong bảng điều khiển Hiệu suất Công cụ của Chrome cho nhà phát triển.
![Các chỉ số đo lường Thời gian người dùng của các danh mục con LCP được hiển thị trong Công cụ của Chrome cho nhà phát triển](https://web.developers.google.cn/static/articles/optimize-lcp/image/user-timings-lcp-parts.png?authuser=5&hl=vi)
Hình ảnh trong kênh Thời gian đặc biệt hữu ích khi xem cùng với kênh Mạng và Luồng chính, vì bạn có thể xem nhanh những gì đang diễn ra trên trang trong những khoảng thời gian này.
Ngoài việc trực quan hoá các phần phụ LCP trong quy trình theo dõi thời gian, bạn cũng có thể sử dụng JavaScript để tính toán tỷ lệ phần trăm của mỗi phần phụ trong tổng thời gian LCP. Với thông tin đó, bạn có thể xác định xem các trang của mình có đáp ứng bảng phân tích tỷ lệ phần trăm đề xuất như mô tả trước đó hay không.
Ảnh chụp màn hình này cho thấy một ví dụ ghi lại tổng thời gian của từng phần phụ LCP, cũng như tỷ lệ phần trăm của phần đó trong tổng thời gian LCP vào bảng điều khiển.
![Thời gian của danh mục con LCP, cũng như tỷ lệ phần trăm LCP của các danh mục phụ đó được in ra bảng điều khiển](https://web.developers.google.cn/static/articles/optimize-lcp/image/the-lcp-sub-part-times.png?authuser=5&hl=vi)
Cả hai hình ảnh này đều được tạo bằng mã sau:
const LCP_SUB_PARTS = [
'Time to first byte',
'Resource load delay',
'Resource load duration',
'Element render delay',
];
new PerformanceObserver((list) => {
const lcpEntry = list.getEntries().at(-1);
const navEntry = performance.getEntriesByType('navigation')[0];
const lcpResEntry = performance
.getEntriesByType('resource')
.filter((e) => e.name === lcpEntry.url)[0];
// Ignore LCP entries that aren't images to reduce DevTools noise.
// Comment this line out if you want to include text entries.
if (!lcpEntry.url) return;
// Compute the start and end times of each LCP sub-part.
// WARNING! If your LCP resource is loaded cross-origin, make sure to add
// the `Timing-Allow-Origin` (TAO) header to get the most accurate results.
const ttfb = navEntry.responseStart;
const lcpRequestStart = Math.max(
ttfb,
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
lcpResEntry ? lcpResEntry.requestStart || lcpResEntry.startTime : 0
);
const lcpResponseEnd = Math.max(
lcpRequestStart,
lcpResEntry ? lcpResEntry.responseEnd : 0
);
const lcpRenderTime = Math.max(
lcpResponseEnd,
// Use LCP startTime (the final LCP time) because there are sometimes
// slight differences between loadTime/renderTime and startTime
// due to rounding precision.
lcpEntry ? lcpEntry.startTime : 0
);
// Clear previous measures before making new ones.
// Note: due to a bug, this doesn't work in Chrome DevTools.
LCP_SUB_PARTS.forEach((part) => performance.clearMeasures(part));
// Create measures for each LCP sub-part for easier
// visualization in the Chrome DevTools Performance panel.
const lcpSubPartMeasures = [
performance.measure(LCP_SUB_PARTS[0], {
start: 0,
end: ttfb,
}),
performance.measure(LCP_SUB_PARTS[1], {
start: ttfb,
end: lcpRequestStart,
}),
performance.measure(LCP_SUB_PARTS[2], {
start: lcpRequestStart,
end: lcpResponseEnd,
}),
performance.measure(LCP_SUB_PARTS[3], {
start: lcpResponseEnd,
end: lcpRenderTime,
}),
];
// Log helpful debug information to the console.
console.log('LCP value: ', lcpRenderTime);
console.log('LCP element: ', lcpEntry.element, lcpEntry.url);
console.table(
lcpSubPartMeasures.map((measure) => ({
'LCP sub-part': measure.name,
'Time (ms)': measure.duration,
'% of LCP': `${
Math.round((1000 * measure.duration) / lcpRenderTime) / 10
}%`,
}))
);
}).observe({type: 'largest-contentful-paint', buffered: true});
Bạn có thể sử dụng mã này nguyên trạng để gỡ lỗi cục bộ hoặc sửa đổi mã để gửi dữ liệu này đến nhà cung cấp phân tích để bạn có thể hiểu rõ hơn về tỷ lệ phân tích LCP trên các trang của mình cho người dùng thực.
Theo dõi thông tin phân tích về LCP bằng tiện ích Chỉ số quan trọng của trang web
Tiện ích Chỉ số quan trọng chính của trang web sẽ ghi lại thời gian LCP, phần tử LCP và bốn phần phụ này trong bảng điều khiển để bạn có thể xem thông tin chi tiết này.
![Ghi nhật ký trên bảng điều khiển của tiện ích Chỉ số quan trọng của trang web, cho biết thời gian của các phần phụ trong LCP](https://web.developers.google.cn/static/articles/optimize-lcp/image/web-vitals-extension-lcp.png?authuser=5&hl=vi)
Tóm tắt
LCP rất phức tạp và thời gian của LCP có thể chịu ảnh hưởng của một số yếu tố. Tuy nhiên, nếu bạn cho rằng việc tối ưu hoá LCP chủ yếu là tối ưu hoá tải tài nguyên LCP, thì việc này có thể đơn giản hoá đáng kể mọi thứ.
Nhìn chung, có thể tóm tắt việc tối ưu hoá LCP trong bốn bước sau:
- Hãy đảm bảo tài nguyên LCP bắt đầu tải sớm nhất có thể.
- Đảm bảo phần tử LCP có thể hiển thị ngay khi tài nguyên của phần tử này tải xong.
- Hãy giảm tối đa thời gian tải của tài nguyên LCP mà không làm giảm chất lượng.
- Cung cấp tài liệu HTML ban đầu nhanh nhất có thể.
Nếu có thể thực hiện các bước này trên trang của mình, bạn sẽ tự tin rằng mình đang cung cấp trải nghiệm tải tối ưu cho người dùng và bạn sẽ thấy điều đó được phản ánh trong điểm LCP thực tế của mình.