Tối ưu hoá thời gian hiển thị nội dung lớn nhất

Thời gian hiển thị nội dung lớn nhất (LCP) là một trong 3 chỉ số 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 trang web, cụ thể là thời gian từ khi người dùng bắt đầu tải trang cho đến khi khối văn bản hoặc hình ảnh 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, trang web phải có LCP từ 2,5 giây trở xuống cho ít nhất 75% lượt truy cập trang.

Giá trị LCP tốt là từ 2,5 giây trở xuống, giá trị kém lớn hơn 4,0 giây và bất kỳ mức độ nào còn lại cần cải thiện
Giá trị LCP tốt là từ 2,5 giây trở xuống.

Một số yếu tố có thể ảnh hưởng đến tốc độ của trình duyệt trong việc tải và hiển thị một trang web, cũng như sự chậm trễ trên bất kỳ yếu tố nào trong số đó cũng có thể ảnh hưởng đáng kể đến LCP.

Hiếm khi việc sửa nhanh một phần của trang lại có thể mang lại sự cải thiện có ý nghĩa cho LCP. Để cải thiện LCP, bạn phải xem toàn bộ quy trình tải và đảm bảo mọi bước trong quá trình tải đều được tối ưu hoá.

Tìm hiểu về chỉ số LCP

Trước khi tối ưu hoá LCP, nhà phát triển phải tìm hiểu xem trang web của họ có vấn đề về LCP hay không và mức độ nghiêm trọng.

Một số công cụ có thể đo lường LCP, nhưng không phải công cụ nào cũng đo LCP theo cùng một cách. Để hiểu được trải nghiệm LCP thực tế của người dùng, bạn phải hiểu được trải nghiệm của người dùng thực tế, thay vì chỉ cho thấy những gì mà một công cụ trong phòng thí nghiệm như Lighthouse hoặc thử nghiệm cục bộ có thể cho thấy. Các công cụ dựa trên phòng thí nghiệm này có thể cung cấp rất nhiều thông tin để giải thích về LCP và giúp bạn cải thiện các chỉ số của mình. Tuy nhiên, việc chỉ kiểm thử trong phòng thí nghiệm không thể hiện hoàn toàn trải nghiệm của người dùng.

Bạn có thể hiển thị dữ liệu LCP dựa trên người dùng thực từ các công cụ Giám sát người dùng thực (rum) được cài đặt trên trang web hoặc thông qua Báo cáo trải nghiệm người dùng trên Chrome (CrUX). Báo cáo này thu thập dữ liệu ẩn danh từ người dùng Chrome thực cho hàng triệu trang web.

Sử dụng dữ liệu CrUX trong PageSpeed Insights

PageSpeed Insights cung cấp quyền truy cập vào dữ liệu CrUX trong phần Khám phá những gì người dùng thực của bạn đang trải nghiệm. Bạn có thể xem thêm dữ liệu chi tiết dựa trên phòng thí nghiệm trong phần Chẩn đoán các vấn đề về hiệu suất. Luôn tập trung vào dữ liệu CrUX trước tiên (nếu có).

Dữ liệu CrUX có trong PageSpeed Insights
Dữ liệu CrUX xuất hiện trong PageSpeed Insights.

Trong trường hợp CrUX không cung cấp dữ liệu (ví dụ: đối với một trang không có đủ lưu lượng truy cập để lấy dữ liệu cấp trang), bạn có thể bổ sung cho CrUX bằng dữ liệu rum được thu thập bằng cách sử dụng API JavaScript chạy trên trang. Lớp này cũng có thể cung cấp nhiều dữ liệu hơn so với CrUX có thể hiển thị dưới dạng tập dữ liệu công khai. Trong phần sau của hướng dẫn này, chúng tôi sẽ giải thích cách thu thập dữ liệu này bằng JavaScript.

Dữ liệu LCP

PageSpeed Insights hiển thị tối đa 4 tập dữ liệu CrUX khác nhau:

  • Dữ liệu thiết bị di động cho URL này
  • Dữ liệu trên máy tính cho URL này
  • Dữ liệu thiết bị di động cho toàn bộ Nguồn gốc
  • Dữ liệu trên máy tính cho toàn bộ Nguồn gốc

Bạn có thể bật/tắt các nút điều khiển này trong các chế độ điều khiển ở trên cùng và trên cùng bên phải của phần 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 nguồn gốc, thì PageSpeed Insights sẽ luôn hiển thị dữ liệu gốc.

PageSpeed Insights trở lại dữ liệu cấp nguồn gốc khi không có dữ liệu cấp url
Khi không có dữ liệu cấp URL, PageSpeed Insights sẽ hiển thị dữ liệu cấp nguồn gốc.

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 đó. Số liệu 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. Người dùng mới thường truy cập vào trang chủ nên các trang này thường được tải mà không có nội dung nào được lưu vào bộ nhớ đệm, khiến chúng trở thành các trang chậm nhất trên trang web.

Việc xem xét 4 danh mục dữ liệu CrUX có thể giúp bạn biết được liệu một vấn đề về LCP chỉ xảy ra trên trang này hay là vấn đề chung trên toàn trang web. Tương tự, báo cáo này có thể cho biết loại thiết bị nào có vấn đề về LCP.

Các chỉ số bổ sung

Các nhà phát triển đang tìm cách tối ưu hoá LCP cũng có thể sử dụng thời gian Thời gian hiển thị nội dung đầu tiên (FCP)Thời gian cho byte đầu tiên (TTFB). Đây là những chỉ số chẩn đoán hiệu quả, có thể cung cấp thông tin chi tiết có giá trị về LCP.

TTFB là thời gian kể từ khi khách truy cập bắt đầu điều hướng đến một trang (ví dụ: nhấp vào đường liên kết), cho đến khi nhận được các byte đầu tiên của tài liệu HTML. 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ể là do các lệnh chuyển hướng nhiều máy chủ, khách truy cập ở xa máy chủ trang web gần nhất, khách truy cập có đ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 các tham số truy vấn.

Khi một trang bắt đầu hiển thị, có thể sẽ có màu hiển thị ban đầu (ví dụ: màu nền), sau đó là một số nội dung xuất hiện (ví dụ: tiêu đề trang web). Giao diện của nội dung ban đầu được đo bằng FCP và sự khác biệt giữa FCP và các chỉ số khác có thể rất rõ ràng.

Sự khác biệt lớn giữa TTFB và FCP có thể cho thấy trình duyệt cần tải xuống nhiều nội dung chặn hiển thị. Đây cũng có thể là dấu hiệu cho thấy trình duyệt phải hoàn thành rất nhiều việc để hiển thị nội dung có ý nghĩa, cho thấy trang web phụ thuộc nhiều vào quá trình kết xuất phía máy khách.

Sự khác biệt 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 được quản lý bằng JavaScript thay vì có sẵn trong HTML ban đầu) hoặc trình duyệt phải 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 PageSpeed Insights Lighthouse

Mục Lighthouse của PageSpeed Insights cung cấp một số hướng dẫn để cải thiện LCP, nhưng 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 thống nhất, 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 rằng dữ liệu CrUX là dữ liệu về trang của bạn chứ không phải nguồn gốc đầy đủ trước khi bạn hành động dựa trên dữ liệu đó.

Nếu cả Lighthouse và CrUX đều cho thấy các giá trị LCP cần cải thiện, thì phần Lighthouse có thể cung cấp hướng dẫn hữu ích về cách cải thiện LCP. Hãy sử dụng bộ lọc LCP để chỉ hiển thị các kết quả 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
Chẩn đoán và đề xuất của Lighthouse để cải thiện LCP.

Bên cạnh Cơ hội cần cải thiện, phần 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ử Thời gian hiển thị nội dung lớn nhất hiển thị thông tin chi tiết hữu ích về các khoảng thời gian khác nhau tạo nên LCP:

Các giai đoạn LCP của Lighthouse
Thông tin phân tích chi tiết về các thành phần LCP của Lighthouse.

Phần tiếp theo sẽ khám phá chi tiết hơn các danh mục phụ của LCP.

Bảng chi tiết LCP

Phần này trình bày phương pháp chia LCP thành các danh mục phụ quan trọng nhất, cùng với các đề xuất cụ thể và các phương pháp hay nhất để tối ưu hoá từng danh mục phụ.

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 chỉ nên bắt đầu với tài liệu HTML ban đầu và 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à các thời điểm tài nguyên LCP bắt đầu và kết thúc) sẽ cho biết liệu 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ô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 (nếu có) do phần tử tải trong thác nước mạng của tất cả tài nguyên được tải trên trang.

Ví dụ: hình ảnh sau đây cho thấy các 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 đòi hỏi một yêu cầu hình ảnh để hiển thị.

Thác nước trên mạng, trong đó các tài nguyên HTML và LCP được làm nổi bật
Biểu đồ thác nước cho thấy thời gian tải cho HTML của trang web và những tài nguyên mà LCP cần.

Đối với một trang được tối ưu hoá tốt, 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 hiển thị nhanh nhất có thể sau khi tài nguyên LCP tải xong. Để giúp hình dung xem một trang cụ thể có tuân theo 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 danh mục con sau:

Thời gian đến 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 được 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ính từ thời điểm 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 để hiển thị (ví dụ: nếu phần tử là một nút văn bản được hiển thị bằng phông chữ hệ thống), thì thời gian này là 0.
Thời gian tải tài nguyên
Thời gian cần thiết để tải chính 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, thì thời gian này là 0.
Độ trễ khi kết xuất phần tử
Khoảng thời gian tính từ khi tài nguyên LCP tải xong đến khi phần tử LCP hiển thị đầy đủ.

LCP của mỗi trang bao gồm bốn danh mục con sau. Không có khoảng cách hay sự chồng chéo giữa các mô-đun này và chúng cộng lại theo thời gian LCP đầy đủ.

Bảng chi tiết về LCP cho thấy 4 danh mục phụ
Cùng một sơ đồ thác nước, với 4 danh mục con LCP được phủ lên tiến trình.

Khi tối ưu hoá LCP, bạn nên cố gắng tối ưu hoá các danh mục phụ này. Tuy nhiên, bạn cần đảm bảo tất cả các danh mục con này đều được tối ưu hoá, vì một số hoạt động tối ưu hoá chuyển thời gian lưu trên phần này sang phần khác thay vì thực sự giảm LCP.

Ví dụ: trong ví dụ về thác nước mạng, việc 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 một định dạng tối ưu hơn (chẳng hạn như AVIF hoặc WebP) sẽ giảm thời gian tải tài nguyên, nhưng sẽ không cải thiện LCP vì thời gian đó trở thành một phần của độ trễ kết xuất phần tử. Nguyên nhân là do phần tử LCP bị ẩn cho đến khi JavaScript liên kết của phần tử đó tải xong, sau đó phần tử này hiển thị.

Thông tin chi tiết tương tự về LCP được hiển thị trước đó, trong đó danh mục phụ thời gian tải tài nguyên được rút ngắn nhưng thời gian LCP tổng thể vẫn giữ nguyên.
Việc rút ngắn thời gian tải tài nguyên sẽ làm tăng độ trễ hiển thị phần tử mà không giảm LCP.

Thời gian tối ưu cho danh mục phụ

Để tối ưu hoá từng danh mục con của LCP, bạn cần hiểu rõ bảng phân tích lý tưởng trong các danh mục phụ này trên một trang được tối ưu hoá hiệu quả.

Hai danh mục phụ liên quan đến sự chậm trễ phải được giảm bớt ở mức tối đa. Hai giải pháp còn lại đều liên quan đến các yêu cầu về mạng vốn thường mất thời gian và không thể tối ưu hoá hoàn toàn.

Dưới đây là mô hình phân phối LCP lý tưởng.

Phần phụ LCP % LCP (Nội dung lớn nhất hiển thị)
Thời gian đến byte đầu tiên (TTFB) Khoảng 40%
Độ trễ khi tải tài nguyên <10%
Thời gian tải tài nguyên Khoảng 40%
Độ trễ khi kết xuất phần tử <10%
TỔNG CỘNG 100%

Những thời điểm này là nguyên tắc chứ không phải là quy tắc nghiêm ngặt. Nếu thời gian LCP của trang liên tục từ 2,5 giây trở xuống, thì việc phân tích sẽ không thực sự quan trọng. Tuy nhiên, nếu các danh mục độ trễ của bạn dài quá mức một cách không cần thiết, bạn sẽ gặp khó khăn khi đạt được mục tiêu 2,5 giây.

Bạn nên xem xét bảng chi tiết thời gian LCP như sau:

  • Bạn phải dành phần lớn thời gian LCP để tải tài liệu HTML và nguồn LCP.
  • Bất cứ lúc nào trước LCP mà một trong hai tài nguyên này không tải đều là cơ hội để cải thiện.

Cách tối ưu hoá từng danh mục

Bây giờ, bạn đã hiểu thời gian của danh mục phụ LCP trông như thế nào 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 riêng mình.

Các phần sau đây trình bày các đề xuất và phương pháp hay nhất khi tối ưu hoá từng danh mục, bắt đầu từ những hoạt động tối ưu hoá có khả năng tạo ra tác động lớn nhất.

Loại bỏ độ trễ khi tải tài nguyên

Mục tiêu của bước này là đảm bảo rằng tài nguyên LCP bắt đầu tải càng sớm càng tốt. Mặc dù về mặt lý thuyết, tài nguyên sớm nhất có thể bắt đầu tải 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 cơ bản là đảm bảo tài nguyên LCP của bạn bắt đầu cùng lúc với tài nguyên đầu tiên mà trang tải.

Sơ đồ 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
Trên trang này, tài nguyên LCP bắt đầu tải ngay sau khi biểu định kiểu tải trước. Có những điểm cần cải thiện ở đây.

Nhìn chung, có 2 yếu tố ảnh hưởng đến tốc độ tải của tài nguyên LCP:

  • Khi tìm thấy tài nguyên.
  • Mức độ ưu tiên của tài nguyên.

Tối ưu hoá khi tìm thấy tài nguyên

Để đảm bảo tài nguyên LCP bắt đầu tải sớm nhất có thể, bạ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. Sau đây là một số ví dụ về các tài nguyên LCP có thể tìm thấy:

  • Một phần tử <img> có thuộc tính src hoặc srcset nằm trong mã đánh dấu HTML ban đầu.
  • Bất kỳ phần tử nào yêu cầu hình nền CSS, miễn là hình ảnh đó được <link rel="preload"> tải trước trong mã đánh dấu HTML (hoặc sử dụng tiêu đề Link).
  • Nút văn bản cần phải có phông chữ trên web để hiển thị, miễn là phông chữ đó được <link rel="preload"> tải trước trong mã đánh dấu HTML (hoặc sử dụng tiêu đề Link).

Dưới đây là một số tài nguyên LCP mà không phát hiện được bằng cách quét phản hồi của tài liệu HTML. Trong mỗi trường hợp, trình duyệt phải chạy một tập lệnh hoặc áp dụng biểu định kiểu thì mới có thể khám phá và bắt đầu tải tài nguyên LCP, đòi hỏi trình duyệt phải đợi các yêu cầu mạng hoàn tất.

  • <img> được tự động thêm vào trang bằng JavaScript.
  • Bất kỳ phần tử nào được tải từng phần bằng thư viện JavaScript ẩn các thuộc tính src hoặc srcset (thường là data-src hoặc data-srcset).
  • Bất kỳ phần tử nào yêu cầu hình nền CSS.

Để 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 tìm thấy 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 của tài nguyên

Ngay cả khi có thể tìm thấy tài nguyên LCP qua mã đánh dấu HTML, tài nguyên đó vẫn có thể không bắt đầu tải sớm nhất là 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 thông tin phỏng đoán ư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 của mình bằ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 rằng hình ảnh đang nằm trong khung nhìn. Điều này thường khiến hình ảnh tải chậm hơn so với bình thường.

Ngay cả khi không tải từng phần, ban đầu các trình duyệt vẫn không tải hình ảnh có mức độ ưu tiên cao vì chúng không phải là tài nguyên chặn hiển thị. Bạn có thể tăng mức độ ưu tiên tải của tài nguyên bằng cách sử dụng thuộc tính fetchpriority như sau:

<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 phần tử đó có thể là phần tử LCP của trang. Tuy nhiên, việc đặt mức độ ưu tiên cao trên nhiều 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 sớm trong phản hồi của 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 các 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 của một số tài nguyên nhất định có thể cung cấp thêm băng thông cho các tài nguyên cần đến nhiều hơn, nhưng hãy cẩn thận đừng lạm dụng. Luôn kiểm tra mức độ ưu tiên của tài nguyên trong DevTools và kiểm thử các thay đổi bằng các công cụ trong phòng thí nghiệm và công cụ 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 mạng của bạn sẽ có dạng như sau, trong đó 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 mạng cho thấy tài nguyên LCP hiện đang bắt đầu cùng lúc với tài nguyên đầu tiên
Giờ đây, tài nguyên LCP bắt đầu tải cùng lúc với biểu định kiểu.

Điểm chính: Một lý do khác khiến tài nguyên LCP của bạn có thể không bắt đầu tải sớm nhất có thể, ngay cả khi có thể phát hiện được từ nguồn HTML, là do tài nguyên được lưu trữ trên một nguồn gốc khác mà trình duyệt phải kết nối trước khi có thể bắt đầu tải tài nguyên. Khi có thể, bạn nên lưu trữ các tài nguyên quan trọng có cùng nguồn gốc với tài nguyên tài liệu HTML để trình duyệt có thể sử dụng lại kết nối hiện có nhằm tiết kiệm thời gian (thông tin thêm về điểm này sau).

Loại bỏ độ trễ kết xuất 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ể thời điểm đó.

Lý do chính khiến phần tử LCP không thể kết xuất ngay sau khi tài nguyên tải xong là nếu quá trình kết xuất bị chặn vì một số lý do khác:

  • Quá trình hiển thị toàn bộ trang sẽ bị chặn do các 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 vì phần tử này đang chờ mã JavaScript tải.
  • Phần tử bị ẩn bởi một số mã khác, chẳng hạn như một thư viện thử nghiệm A/B chưa quyết định nhóm thử nghiệm nào sẽ đưa người dùng vào.
  • Luồng chính bị chặn do các tác vụ dài và quá trình kết xuất phải đợi cho đến khi các tác vụ dài đó hoàn tất.

Các phần sau đây giải thích cách giải quyết các nguyên nhân phổ biến nhất gây ra độ trễ khi kết xuất phần tử không cần thiết.

Giảm hoặc cùng dòng biểu định kiểu chặn hiển thị

Biểu định kiểu được tải từ kết xuất khối đánh dấu HTML của tất cả nội dung theo sau. Đây thường là một điều tốt vì biểu định kiểu cho phép biểu định kiểu có hiệu lực trước khi các phần tử khác tải. 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ì biểu định kiểu sẽ ngăn phần tử LCP hiển thị ngay cả sau khi tài nguyên đã tải xong, như minh hoạ trong ví dụ sau:

Sơ đồ dạng thác nước trên mạng cho thấy một tệp CSS lớn chặn kết xuất phần tử LCP vì phần tử này mất nhiều thời gian tải hơn so với tài nguyên LCP
Hình ảnh và biểu định kiểu bắt đầu tải cùng một lúc, nhưng hình ảnh không thể hiển thị cho đến khi biểu định kiểu sẵn sàng.

Để khắc phục vấn đề này, bạn có thể:

  • nội dòng biểu định kiểu vào HTML để tránh yêu cầu mạng bổ sung; hoặc,
  • giảm kích thước của biểu định kiểu.

Việc cùng dòng biểu định kiểu chỉ hiệu quả để giảm LCP nếu biểu định kiểu có kích thước nhỏ. Tuy nhiên, nếu biểu định kiểu mất nhiều thời gian tải hơn so với tài nguyên LCP, thì có thể tài nguyên đó sẽ quá lớn để tải cùng dòng một cách hiệu quả. Vì vậy, bạn nên giảm độ phức tạp của biểu định kiểu như sau:

Hoãn hoặc chặn JavaScript cùng dòng

Bạn nên thiết lập để tất cả tập lệnh trên các trang không đồng bộ bằng cách sử dụng thuộc tính async hoặc defer. Việc sử dụng tập lệnh đồng bộ hầu như luôn không hiệu quả đối với hiệu suất.

Tuy nhiên, nếu có JavaScript cần chạy sớm nhất có thể khi tải trang, bạn có thể cải thiện LCP bằng cách chèn các tập lệnh nhỏ vào cùng dòng để giảm thời gian trình duyệt dành cho việc chờ các yêu cầu mạng.

Nên
<head>
  <script>
    // Inline script contents directly in the HTML.
    // IMPORTANT: only do this for very small scripts.
  </script>
</head>
Không nên
<head>
  <script src="/path/to/main.js"></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 của bạn trên máy chủ và phản hồi các yêu cầu về tài liệu HTML bằng mã đánh dấu HTML đầy đủ.

SSR giúp tối ưu hoá LCP theo những cách sau:

  • Công cụ này giúp người dùng có thể tìm thấy tài nguyên của bạn qua nguồn HTML, như đã thảo luận trong bài viết Loại bỏ độ trễ tải tài nguyên.
  • Lớp này giúp trang của bạn không cần phải hoàn tất thêm các yêu cầu JavaScript trước khi có thể hiển thị.

Nhược điểm chính của SSR là yêu cầu thêm thời gian xử lý của máy chủ, điều này 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 mạng và thiết bị của người dùng thì không.

Bạn cũng nên tạo trang HTML trong một bước xây dựng thay vì theo yêu cầu để đạt được hiệu suất tốt hơn. Phương pháp này được gọi là tạo trang web tĩnh (SSG) hoặc kết xuất trước.

Chia nhỏ các tác vụ dài

Ngay cả khi bạn đã làm theo tất cả lời khuyên trên và mã JavaScript của bạn không chặn hiển thị hay chịu trách nhiệm hiển thị các phần tử, mã này vẫn có thể trì hoãn LCP.

Lý do phổ biến nhất là khi một trang tải một tệp JavaScript lớn, trình duyệt sẽ cần thời gian để phân tích cú pháp và thực thi mã trên chuỗi chính của trang. Điều này có nghĩa là ngay cả khi tài nguyên LCP đã được tải xuống đầy đủ, tài nguyên đó vẫn có thể phải đợi để kết xuất cho đến khi thực thi xong một tập lệnh không liên quan.

Tất cả các trình duyệt đều hiển thị hình ảnh trên luồng chính, tức là mọi thao tác chặn luồng chính cũng có thể dẫn đến độ trễ hiển thị phần tử không cần thiết. Do đó, bạn nên chia nhỏ một tệp JavaScript lớn thành nhiều tệp tập lệnh để mỗi tệp có thể được phân tích cú pháp khi cần.

Giảm thời gian tải tài nguyên

Mục tiêu của bước này là giảm thời gian trình duyệt dành cho việc chuyển tài nguyên qua mạng sang thiết bị của người dùng. Nhìn chung, có một số cách để thực hiện việc này:

  • 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 sử dụng mạng.

Giảm kích thước của tài nguyên

Tài nguyên LCP thường là hình ảnh hoặc phông chữ trên web. Hướng dẫn sau đây cung cấp chi tiết về cách giảm kích thước của cả hai:

Giảm khoảng cách mà tài nguyên phải di chuyển

Bạn cũng có thể giảm thời gian tải bằng cách đặt máy chủ càng gần người dùng càng tốt. Cách tốt nhất để làm việc này là sử dụng mạng phân phối nội dung (CDN).

Trên thực tế, các CDN hình ảnh đặc biệt hữu ích vì cả hai đều giúp giảm khoảng cách tài nguyên phải di chuyển và thường giảm kích thước tài nguyên theo các chiến lược đã đề cập trước đó.

Điểm chính: CDN hình ảnh là một cách tuyệt vời để giảm thời gian tải tài nguyên. Tuy nhiên, việc sử dụng miền của bên thứ ba để lưu trữ hình ảnh sẽ làm phát sinh thêm chi phí kết nối. Mặc dù việc kết nối trước với nguồn gốc có thể giảm thiểu một phần chi phí này, nhưng cách tốt nhất là phân phát hình ảnh từ cùng nguồn gốc với tài liệu HTML của bạn. Để cho phép việc này, nhiều CDN cho phép bạn proxy các yêu cầu từ nguồn gốc của bạn đến nguồn của họ.

Giảm tranh chấp về băng thông mạng

Nếu trang của bạn tải nhiều tài nguyên cùng lúc, thì bất kỳ tài nguyên nào cũng có thể mất nhiều thời gian để tải. Vấn đề này được gọi là tranh chấp mạng.

Nếu bạn đã cung cấp fetchpriority cao cho tài nguyên LCP của mình 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 các tài nguyên có mức độ ưu tiên thấp hơn cạnh tranh với tài nguyên đó. Tuy nhiên, việc tải quá nhiều tài nguyên cùng một lúc vẫn có thể ảnh hưởng đến LCP, đặc biệt nếu nhiều tài nguyên trong số đó có fetchpriority cao. Bạn nên giảm tranh chấp mạng bằng cách đảm bảo rằng chỉ các tài nguyên có fetchpriority cao là những tài nguyên cần tải nhanh nhất.

Loại bỏ hoàn toàn thời gian sử dụng mạng

Cách tốt nhất để giảm thời gian tải tài nguyên là loại bỏ hoàn toàn mạng khỏi quy trình này. Nếu bạn phân phát tài nguyên của mình bằng một 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 những tài nguyên đó lần thứ hai sẽ được phân phát từ bộ nhớ đệm, nhờ đó giảm thời gian tải tài nguyên về cơ bản là bằng không.

Nếu tài nguyên LCP của bạn là một phông chữ web, thì ngoài việc giảm kích thước phông chữ web, bạn nên cân nhắc xem có cần chặn hiển thị khi tải tài nguyên phông chữ trên web hay không. Nếu bạn đặt giá trị font-display của bất kỳ giá trị nào khác ngoài auto hoặc block, thì văn bản sẽ luôn hiển thị trong khi tải và LCP không phải đợi thêm yêu cầu mạng.

Cuối cùng, nếu tài nguyên LCP nhỏ, bạn nên đặt nội tuyến các tài nguyên dưới dạng URI dữ liệu để loại bỏ yêu cầu mạng bổ sung. Tuy nhiên, việc sử dụng URI dữ liệu có một số hạn chế: phương pháp này ngăn các tài nguyên được lưu vào bộ nhớ đệm và có thể gây ra độ trễ hiển thị lâu hơn trong một số trường hợp do chi phí giải mã tăng thêm.

4. Giảm thời gian xuống byte đầu tiên

Mục tiêu của bước này là phân phối HTML ban đầu nhanh nhất có thể. 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, đó 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 mọi bước sau đó. Không có gì có thể xảy ra trên giao diện người dùng cho đến khi phần phụ trợ phân phối byte nội dung đầu tiên đó. Vì vậy, mọi việc bạn có thể làm để tăng tốc TTFB 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 nhanh là khách truy cập đến thông qua nhiều lệnh chuyển hướng, chẳng hạn như từ quảng cáo hoặc đường liên kết được rút ngắn. Luôn giảm thiểu số lượng lệnh chuyển hướng mà khách truy cập phải chờ qua.

Một nguyên nhân phổ biến khác là khi không thể sử dụng nội dung đã lưu vào bộ nhớ đệm từ máy chủ cạnh CDN, đòi hỏi tất cả các yêu cầu phải được chuyển hướng hoàn toàn 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 các tham số URL riêng biệt để phân tích, ngay cả khi họ không dẫn đến các trang khác nhau.

Để biết hướng dẫn cụ thể về cách giảm TTFB, hãy xem bài viết Tối ưu hoá TTFB.

Theo dõi bảng chi tiết LCP trong JavaScript

Thông tin về thời gian của tất cả các danh mục con LCP đều có trong JavaScript thông qua tổ hợp các API hiệu suất sau đây:

Việc tính toán các giá trị thời gian này trong JavaScript cho phép bạn gửi chúng đến một nhà cung cấp phân tích hoặc ghi chúng vào các công cụ cho nhà phát triể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 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:

Thời gian người dùng
  đo lường các danh mục con LCP được trực quan hoá trong Công cụ của Chrome cho nhà phát triển
Kênh quản lý thời gian cho biết tiến trình cho các danh mục con LCP.

Hình ảnh trong Theo dõi Thời gian đặc biệt hữu ích cùng với các kênh Mạng và Luồng chính, cho phép bạn xem những hoạt động khác đang diễn ra trên trang trong các khoảng thời gian này.

Bạn cũng có thể dùng JavaScript để tính toán tỷ lệ phần trăm trong tổng thời gian LCP mà mỗi danh mục phụ chiếm, nhằm xác định xem các trang có đáp ứng thông tin chi tiết theo tỷ lệ phần trăm đề xuất 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 danh mục con LCP vào bảng điều khiển, cũng như tỷ lệ phần trăm của danh mục con đó trên tổng thời gian LCP.

Thời gian của danh mục con LCP, cũng như tỷ lệ phần trăm LCP của chúng, được in ra bảng điều khiển
Thời gian và tỷ lệ phần trăm cho danh mục con LCP.

Cả hai hình ảnh trực quan này đều được tạo bằng mã sau:

const LCP_SUB_PARTS = [
  'Time to first byte',
  'Resource load delay',
  'Resource load time',
  '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 một nhà cung cấp phân tích. Nhờ đó, bạn có thể hiểu rõ hơn về dữ liệu phân tích LCP của các trang đối với người dùng thực.

Theo dõi bảng phân tích LCP bằng tiện ích Các chỉ số quan trọng về trang web

Tiện ích Các chỉ số quan trọng về trang web ghi nhật ký thời gian LCP, phần tử LCP và 4 danh mục con trong nhật ký Play Console để cho thấy thông tin phân tích chi tiết này.

Ảnh chụp màn hình ghi nhật ký trên bảng điều khiển của tiện ích Các chỉ số quan trọng về trang web cho thấy dấu thời gian của các phần phụ LCP
Bảng điều khiển Bảng điều khiển cho tiện ích Các chỉ số quan trọng về trang web cho thấy thông tin chi tiết về LCP.