Các vấn đề chính về hiệu suất

Hiện tại, hình ảnh là tài sản lớn nhất trên web xét về cả tổng kích thước chuyểnsố yêu cầu trên mỗi trang. Tổng kích thước chuyển của trang web trung bình là khoảng 2 MB, tính đến tháng 6 năm 2022, trong đó chỉ riêng hình ảnh đã chiếm gần một nửa. Không quá lời khi nói rằng việc tối ưu hoá các yêu cầu về hình ảnh có thể là biện pháp tối ưu hoá hiệu suất lớn nhất mà bạn có thể thực hiện.

Sau đó, bạn sẽ tìm hiểu cách hình ảnh thích ứng đã được phát triển để giúp giải quyết các vấn đề tạo ra bằng cách cố gắng phân phát một hình ảnh cho mọi trường hợp. Trong phần này, hãy khám phá các chỉ số hiệu suất chính liên quan đến hình ảnh và cách cải thiện chúng.

Trì hoãn yêu cầu liên quan đến hình ảnh

Mặc dù bạn sắp tìm hiểu một số cách để đảm bảo yêu cầu hình ảnh nhỏ và hiệu quả nhất có thể, nhưng yêu cầu hình ảnh nhanh nhất sẽ luôn là yêu cầu không bao giờ được thực hiện. Vì vậy, ngay từ đầu tôi muốn chia sẻ điều có thể là thay đổi có tác động lớn nhất mà bạn có thể thực hiện trong cách phân phối thành phần hình ảnh cho người dùng: thuộc tính loading="lazy".

<img src="image.jpg" loading="lazy" alt="…">

Thuộc tính này đảm bảo rằng các yêu cầu đối với hình ảnh không được thực hiện cho đến khi gần với khung nhìn của người dùng, trì hoãn hình ảnh từ lượt tải trang ban đầu (thời gian trình duyệt bận rộn nhất) và xoá các yêu cầu đó khỏi đường dẫn hiển thị quan trọng.

Đơn giản như trong thực tế, việc sử dụng thuộc tính này có thể tác động tích cực rất lớn đến hiệu suất: một hình ảnh không bao giờ nằm trong khung nhìn của người dùng sẽ không bao giờ được yêu cầu và không lãng phí băng thông vào những hình ảnh mà người dùng sẽ không bao giờ nhìn thấy.

Tuy nhiên, có một khó khăn là: việc trì hoãn các yêu cầu đó có nghĩa là bạn không nên tận dụng các quy trình được tối ưu hoá siêu tốc của trình duyệt để yêu cầu hình ảnh càng sớm càng tốt. Nếu loading="lazy" được sử dụng trên các phần tử img ở đầu bố cục (và do đó có nhiều khả năng sẽ nằm trong khung nhìn của người dùng khi trang được tải lần đầu tiên), thì những hình ảnh này có thể khiến người dùng cuối cảm thấy chậm hơn đáng kể.

Mức độ ưu tiên tìm nạp

Thuộc tính loading là một ví dụ cho thấy một nỗ lực bao quát hơn về tiêu chuẩn web nhằm mang lại cho nhà phát triển nhiều quyền kiểm soát hơn về cách trình duyệt web ưu tiên các yêu cầu.

Bạn có thể đã biết các phương pháp cơ bản để tìm nạp mức độ ưu tiên của trình duyệt: ví dụ: yêu cầu tệp CSS bên ngoài trong <head> của tài liệu được coi là đủ thiết yếu để chặn việc hiển thị, trong khi yêu cầu tệp JavaScript bên ngoài ngay phía trên </body> sẽ bị trì hoãn cho đến khi quá trình hiển thị hoàn tất. Nếu giá trị của thuộc tính loading trên <img> là "lazy", thì yêu cầu hình ảnh có liên quan sẽ bị trì hoãn cho đến khi trình duyệt xác định rằng người dùng sẽ nhìn thấy yêu cầu đó. Nếu không, hình ảnh đó sẽ có mức độ ưu tiên giống như mọi hình ảnh khác trên trang.

Thuộc tính fetchpriority nhằm cung cấp cho nhà phát triển quyền kiểm soát chi tiết hơn đối với mức độ ưu tiên của tài sản, cho phép bạn gắn cờ các tài nguyên là có mức độ ưu tiên "cao" và "thấp" so với các tài nguyên cùng loại. Các trường hợp sử dụng cho fetchpriority tương tự như thuộc tính loading, mặc dù có phạm vi rộng hơn nhiều. Ví dụ: bạn có thể sử dụng fetchpriority="low" trên một hình ảnh chỉ được hiển thị sau tương tác của người dùng (cho dù hình ảnh đó có nằm trong khung nhìn của người dùng hay không) để ưu tiên các hình ảnh hiển thị ở những nơi khác trên trang hoặc fetchpriority="high" để ưu tiên một hình ảnh mà bạn biết sẽ hiển thị ngay lập tức trong khung nhìn ngay khi trang được kết xuất.

Xin lưu ý rằng fetchpriority khác với loading ở chỗ về cơ bản không thay đổi hành vi của trình duyệt. Trình duyệt này không hướng dẫn trình duyệt tải một số thành phần trước các thành phần khác mà cung cấp bối cảnh quan trọng cho các quyết định liên quan đến việc yêu cầu tài sản.

Đo lường tác động của hình ảnh

Khi tối ưu hoá thành phần hình ảnh, hiệu suất nhận biết thường quan trọng và khó đo lường hơn so với việc chỉ đo tổng kích thước chuyển.

Các chỉ số quan trọng về trang web cung cấp hướng dẫn và chỉ số có thể hành động và có thể đo lường để cải thiện trải nghiệm của người dùng trên web, nêu bật các vấn đề như thời gian phản hồi chậm trên máy chủ web, vấn đề về việc kết xuất và độ trễ tương tác. Các chỉ số quan trọng về trang web là một tập hợp con của các mục tiêu này, tập trung vào trải nghiệm trực tiếp của người dùng trên một trang riêng lẻ – một nhóm các phép đo kỹ thuật cùng nhau xác định tốc độ cảm nhận của người dùng đối với trải nghiệm.

Điểm số tổng hợp về mức thay đổi bố cục

Điểm số tổng hợp về mức thay đổi bố cục (CLS) là thước đo về độ ổn định của hình ảnh. Đây là chỉ số cho biết mức độ thay đổi bố cục của nội dung trên một trang khi nội dung được tải và trang hiển thị. Bất kỳ người dùng nào dành một lượng thời gian đáng kể trên web đã bị mất vị trí trong một loạt văn bản dài do một trang "nhảy" khi phông chữ web hoặc nguồn hình ảnh bị trễ đột nhiên hiển thị hoặc có một phần tử tương tác đột nhiên di chuyển ra khỏi con trỏ của bạn. CLS cao là một vấn đề rắc rối và tệ nhất là nguyên nhân gây ra lỗi người dùng, chẳng hạn như nút "huỷ" chuyển sang không gian bị nút "xác nhận" chiếm trước đó giống như khi người dùng nhấp vào.

Với thời gian tải cao và không gian mà chúng có thể chiếm trong một bố cục, lý do hình ảnh là nguyên nhân phổ biến dẫn đến điểm CLS cao.

Nhờ những thay đổi tương đối gần đây trong các trình duyệt hiện đại, bạn có thể dễ dàng tránh bị điểm CLS cao do hình ảnh.

Nếu đã làm việc với giao diện người dùng được vài năm, bạn sẽ quen thuộc với các thuộc tính widthheight trên <img>: trước khi CSS được áp dụng rộng rãi, đây là cách duy nhất để kiểm soát kích thước của hình ảnh.

<img src="image.jpg" height="200" width="400" alt="…">

Các thuộc tính này không được sử dụng trong nỗ lực nhằm tách biệt các vấn đề về định kiểu với mã đánh dấu, đặc biệt là vì thiết kế web thích ứng khiến chúng ta phải chỉ định kích thước dựa trên phần trăm thông qua CSS. Trong thời kỳ đầu của thiết kế web thích ứng, bạn nên "xoá các thuộc tính widthheight không dùng đến" vì các giá trị mà chúng ta đã chỉ định trong CSS — max-width: 100%height: auto — sẽ thay thế các thuộc tính này.

<img src="image.jpg" alt="…">
img {
  max-width: 100%;
  height: auto;
}

Sau khi xoá các thuộc tính heightwidth như trong ví dụ trước, phương thức duy nhất mà trình duyệt có để xác định chiều cao của hình ảnh trong trường hợp này là yêu cầu nguồn, phân tích cú pháp và hiển thị nguồn ở tỷ lệ khung hình nội tại, dựa trên chiều rộng của không gian chiếm trong bố cục sau khi áp dụng biểu định kiểu. Phần lớn quá trình này diễn ra sau khi trang được hiển thị, với chiều cao mới được tính toán làm thay đổi bố cục thêm.

Kể từ năm 2019, chúng tôi đã cập nhật hành vi của trình duyệt để xử lý các thuộc tính widthheight theo cách khác nhau. Thay vì sử dụng giá trị của các thuộc tính này để xác định kích thước cố định, dựa trên pixel của một phần tử img trong bố cục, các thuộc tính này có thể được xem là thể hiện tỷ lệ khung hình của hình ảnh, mặc dù cú pháp là giống nhau. Các trình duyệt hiện đại sẽ chia các giá trị này với nhau để xác định tỷ lệ khung hình nội tại của phần tử img trước khi trang hiển thị, cho phép trang đó đặt trước không gian mà hình ảnh sẽ chiếm khi bố cục hiển thị.

Theo quy tắc, bạn luôn nên sử dụng các thuộc tính heightwidth trên <img>, với các giá trị khớp với kích thước nội tại của nguồn hình ảnh – miễn là bạn đảm bảo rằng bạn đã chỉ định height: auto cùng với max-width: 100% để ghi đè chiều cao từ thuộc tính HTML.

<img src="image.jpg" height="200" width="400" alt="…">
img {
  max-width: 100%;
  height: auto;
}

Khi sử dụng các thuộc tính widthheight trên các phần tử <img>, bạn sẽ tránh được điểm CLS cao do hình ảnh.

Điều quan trọng bạn cần lưu ý là không có nhược điểm nào trong cách tiếp cận này, vì phương pháp này dựa vào hành vi lâu đời của trình duyệt – mọi trình duyệt có hỗ trợ CSS cơ bản đều sẽ hoạt động như bình thường, trong đó các thuộc tính heightwidth trong mã đánh dấu bị ghi đè bởi kiểu của bạn.

Mặc dù các thuộc tính widthheight tránh các vấn đề về CLS bằng cách dành riêng không gian bố cục cần thiết cho hình ảnh của bạn, nhưng việc hiển thị người dùng với một khoảng trống hoặc phần giữ chỗ chất lượng thấp trong khi chờ hình ảnh được chuyển và kết xuất cũng không lý tưởng. Mặc dù có một số việc bạn có thể làm để giảm thiểu tác động có thể đo lường và nhận biết được của hình ảnh tải chậm, nhưng cách duy nhất để trình bày hình ảnh kết xuất đầy đủ cho người dùng nhanh hơn là giảm kích thước truyền của hình ảnh đó.

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) đo thời gian cần để kết xuất phần tử "có nội dung" lớn nhất trong khung nhìn của người dùng – phần tử nội dung chiếm tỷ lệ phần trăm lớn nhất trên trang hiển thị. Có vẻ như đây là một chỉ số quá cụ thể, nhưng xét về góc độ của người dùng thì yếu tố này đóng vai trò là proxy thực tế cho điểm mà phần lớn trang đã hiển thị. LCP là một chỉ số đo lường quan trọng về hiệu suất (nhận thấy được).

Các chỉ số như DOMContentLoaded hoặc sự kiện window.onload có thể hữu ích cho việc xác định thời điểm quá trình tải trang hiện tại đã hoàn tất về mặt kỹ thuật, nhưng không nhất thiết phải tương ứng với trải nghiệm của người dùng trên trang. Sự chậm trễ nhỏ trong việc hiển thị một phần tử bên ngoài khung nhìn của người dùng sẽ được tính vào các chỉ số này, nhưng có thể người dùng thực tế sẽ hoàn toàn không phát hiện được. LCP dài có nghĩa là ấn tượng đầu tiên của người dùng về một trang (nội dung quan trọng nhất bên trong khung nhìn hiện tại) là trang đó chậm hoặc bị hỏng hoàn toàn.

Cảm nhận của người dùng mà LCP ghi nhận có tác động trực tiếp đến trải nghiệm người dùng. Một thử nghiệm do Vodafone thực hiện năm ngoái cho thấy mức cải thiện 31% LCP không chỉ giúp tăng 8% doanh số bán hàng – một kết quả rất khả quan – mà tổng số người dùng của Vodafone đã tăng 15% về số lượng khách truy cập đã trở thành khách hàng tiềm năng ("tỷ lệ khách hàng tiềm năng") và tăng 11% số người dùng ghé thăm giỏ hàng ("giỏ hàng").

Trên hơn 70% trang web, phần tử lớn nhất trong khung nhìn ban đầu liên quan đến hình ảnh, ở dạng phần tử <img> độc lập hoặc phần tử có hình nền. Nói cách khác, 70% điểm LCP của các trang dựa trên hiệu suất của hình ảnh. Bạn không cần phải tưởng tượng nhiều để hiểu lý do: những hình ảnh và biểu trưng lớn, thu hút sự chú ý rất có khả năng được tìm thấy "trong màn hình đầu tiên".

LCP được làm nổi bật trong bảng điều khiển của trang web.dev

Có một vài bước bạn có thể thực hiện để tránh chậm trễ LCP: trước tiên, đừng bao giờ chỉ định loading="lazy" trên hình ảnh "trong màn hình đầu tiên", vì việc trì hoãn yêu cầu cho đến khi trang đã hiển thị có thể có tác động tiêu cực rất lớn đến điểm LCP của bạn. Thứ hai, việc sử dụng fetchpriority="high" có thể thông báo cho trình duyệt biết rằng việc chuyển hình ảnh này nên được ưu tiên so với các hình ảnh khác trên trang.

Sau khi lưu ý những quy tắc đó, điều quan trọng nhất bạn có thể làm để cải thiện điểm LCP của trang là giảm thời gian cần thiết để truyền và hiển thị những hình ảnh đó. Để làm được điều đó, bạn cần duy trì các nguồn hình ảnh nhỏ và hiệu quả nhất có thể (tất nhiên là không hy sinh chất lượng) và đảm bảo rằng người dùng chỉ nhận được các thành phần hình ảnh phù hợp nhất với ngữ cảnh duyệt web của họ.

Kết luận

Thành phần hình ảnh gây tiêu hao nhiều nhất trên băng thông của người dùng — băng thông bị sử dụng vì không chuyển mọi nội dung khác cần thiết để hiển thị một trang. Hình ảnh gây ra những vấn đề nghiêm trọng về mặt hiệu suất cảm nhận được, cả trong và sau khi bố cục trang xung quanh được hiển thị. Nói một cách ngắn gọn: thành phần hình ảnh có thể gây thiệt hại.

Khó khăn như vậy, mặc dù "web sẽ tốt hơn nếu có ít hình ảnh hơn" chắc chắn sẽ đúng về mặt hiệu suất nếu chỉ xét đến hiệu suất, thì nó cũng sẽ khiến người dùng cảm thấy bất đồng đáng kể. Hình ảnh là một phần quan trọng của web và bạn không nên làm giảm chất lượng của nội dung có ý nghĩa chỉ vì hiệu suất.

Trong phần còn lại của khoá học này, bạn sẽ tìm hiểu về những công nghệ hỗ trợ thành phần hình ảnh và kỹ thuật giảm thiểu tác động đến hiệu suất mà không làm ảnh hưởng đến chất lượng.