Hiệu suất hình ảnh

Hình ảnh thường là tài nguyên nặng nhấtphổ biến nhất trên web. Do đó, việc tối ưu hoá hình ảnh có thể cải thiện đáng kể hiệu suất trên trang web của bạn. Trong hầu hết các trường hợp, việc tối ưu hoá hình ảnh đồng nghĩa với việc giảm thời gian kết nối mạng bằng cách gửi ít byte hơn. Tuy nhiên, bạn cũng có thể tối ưu hoá số byte được gửi đến người dùng bằng cách phân phát hình ảnh có kích thước phù hợp với thiết bị của người dùng.

Bạn có thể thêm hình ảnh vào một trang bằng cách sử dụng phần tử <img> hoặc <picture> hoặc thuộc tính background-image CSS.

Kích thước hình ảnh

Tối ưu hoá đầu tiên bạn có thể thực hiện khi sử dụng tài nguyên hình ảnh là hiển thị hình ảnh ở kích thước chính xác. Trong trường hợp này, thuật ngữ kích thước dùng để chỉ kích thước của hình ảnh. Nếu không xem xét đến yếu tố nào khác, hình ảnh hiển thị trong vùng chứa 500 pixel x 500 pixel sẽ có kích thước tối ưu là 500 x 500 pixel. Ví dụ: việc sử dụng hình ảnh vuông 1000 pixel có nghĩa là hình ảnh sẽ lớn gấp đôi so với mức cần thiết.

Tuy nhiên, có nhiều biến liên quan đến việc chọn kích thước hình ảnh phù hợp, khiến cho việc chọn kích thước hình ảnh phù hợp trong mọi trường hợp trở nên khá phức tạp. Năm 2010, khi iPhone 4 ra mắt, độ phân giải màn hình (640x960) đã gấp đôi độ phân giải màn hình của iPhone 3 (320x480). Tuy nhiên, kích thước vật lý của màn hình iPhone 4 vẫn tương đương với iPhone 3.

Việc hiển thị mọi thứ ở độ phân giải cao hơn sẽ giúp văn bản và hình ảnh nhỏ hơn đáng kể — chính xác bằng một nửa kích thước trước đây. Thay vào đó, 1 pixel trở thành 2 pixel thiết bị. Đây được gọi là tỷ lệ pixel trên thiết bị (DPR). iPhone 4 (và nhiều mẫu iPhone được phát hành sau đó) có DPR là 2.

Xem lại ví dụ trước, nếu thiết bị có DPR là 2 và hình ảnh hiển thị trong vùng chứa 500 pixel x 500 pixel, thì hình ảnh vuông 1000 pixel (gọi là kích thước nội tại) hiện là kích thước tối ưu. Tương tự, nếu thiết bị có DPR là 3, thì hình ảnh vuông 1500 pixel sẽ là kích thước tối ưu.

srcset

Phần tử <img> hỗ trợ thuộc tính srcset, cho phép bạn chỉ định danh sách nguồn hình ảnh mà trình duyệt có thể sử dụng. Mỗi nguồn hình ảnh được chỉ định phải bao gồm URL hình ảnh và thông tin mô tả chiều rộng hoặc mật độ pixel.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>

Đoạn mã HTML ở trên sử dụng trình mô tả mật độ pixel để gợi ý cho trình duyệt sử dụng image-500.png trên các thiết bị có DPR là 1, image-1000.jpg trên các thiết bị có DPR là 2 và image-1500.jpg trên các thiết bị có DPR là 3.

Mặc dù tất cả những điều này có vẻ đã khô ráo, nhưng DPR của màn hình không phải là yếu tố duy nhất cần cân nhắc khi chọn hình ảnh tối ưu cho một trang nhất định. Bố cục của trang cũng là một yếu tố khác cần cân nhắc.

sizes

Giải pháp trước đây chỉ hiệu quả nếu bạn hiển thị hình ảnh ở cùng một kích thước pixel CSS trên tất cả các khung nhìn. Trong nhiều trường hợp, bố cục của một trang và kích thước của vùng chứa cùng với trang đó sẽ thay đổi tuỳ thuộc vào thiết bị của người dùng.

Thuộc tính sizes cho phép bạn chỉ định một tập hợp các kích thước nguồn, trong đó mỗi kích thước nguồn bao gồm một điều kiện về nội dung đa phương tiện và một giá trị. Thuộc tính sizes mô tả kích thước hiển thị dự kiến của hình ảnh bằng pixel CSS. Khi kết hợp với chỉ số mô tả chiều rộng srcset, trình duyệt có thể chọn nguồn hình ảnh phù hợp nhất với thiết bị của người dùng.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
  sizes="(min-width: 768px) 500px, 100vw"
>

Trong đoạn mã HTML trước đó, thuộc tính srcset chỉ định danh sách hình ảnh ứng viên mà trình duyệt có thể chọn, được phân tách bằng dấu phẩy. Mỗi đề xuất trong danh sách bao gồm URL của hình ảnh, theo sau là một cú pháp biểu thị chiều rộng nội tại của hình ảnh. Kích thước nội tại của một hình ảnh là kích thước của hình ảnh. Ví dụ: phần mô tả 1000w biểu thị chiều rộng nội tại của hình ảnh là rộng 1000 pixel.

Bằng cách sử dụng thông tin này, trình duyệt sẽ đánh giá điều kiện về nội dung đa phương tiện trong thuộc tính sizes và trong trường hợp này, trình duyệt được hướng dẫn rằng nếu chiều rộng khung nhìn của thiết bị vượt quá 768 pixel, thì hình ảnh sẽ được hiển thị ở chiều rộng 500 pixel. Trên các thiết bị nhỏ hơn, hình ảnh sẽ hiển thị ở kích thước 100vw hoặc với chiều rộng tối đa của khung nhìn.

Sau đó, trình duyệt có thể kết hợp thông tin này với danh sách nguồn hình ảnh srcset để tìm hình ảnh tối ưu. Ví dụ: nếu người dùng sử dụng một thiết bị di động có chiều rộng màn hình là 320 pixel với DPR là 3, thì hình ảnh sẽ hiển thị ở 320 CSS pixels x 3 DPR = 960 device pixels. Trong ví dụ này, hình ảnh có kích thước gần nhất sẽ là image-1000.jpg có chiều rộng nội tại là 1000 pixel (1000w).

Định dạng tệp

Các trình duyệt hỗ trợ nhiều định dạng tệp hình ảnh khác nhau. Các định dạng hình ảnh hiện đại như WebPAVIF có thể có khả năng nén tốt hơn so với PNG hoặc JPEG, giúp giảm kích thước tệp hình ảnh và do đó mất ít thời gian hơn để tải xuống. Bằng cách phân phát hình ảnh ở định dạng hiện đại, bạn có thể giảm thời gian tải của tài nguyên. Việc này có thể khiến Thời gian hiển thị nội dung lớn nhất (LCP) thấp hơn.

WebP là một định dạng được hỗ trợ rộng rãi và hoạt động trên tất cả các trình duyệt hiện đại. WebP thường có khả năng nén tốt hơn so với JPEG, PNG hoặc GIF, cung cấp cả nén tổn haonén không tổn hao. WebP cũng hỗ trợ độ trong suốt của kênh alpha ngay cả khi sử dụng tính năng nén có tổn hao – một tính năng mà bộ mã hoá và giải mã JPEG không cung cấp.

AVIF là một định dạng hình ảnh mới, mặc dù không được hỗ trợ rộng rãi như WebP, nhưng vẫn được hỗ trợ khá tốt trên các trình duyệt. AVIF hỗ trợ cả nén có tổn hao và không tổn hao. Trong một số trường hợp, các thử nghiệm cho thấy mức tiết kiệm hơn 50% so với JPEG. AVIF cũng cung cấp các tính năng Gam màu rộng (WCG)Dải động cao (HDR).

Nén

Có hai cách nén hình ảnh:

  1. Nén nội dung bị mất
  2. Nén không tổn hao

Tính năng nén có tổn hao hoạt động bằng cách giảm độ chính xác của hình ảnh thông qua quá trình lượng tử hoá và thông tin màu sắc bổ sung có thể bị loại bỏ bằng cách sử dụng phương pháp lấy mẫu phụ sắc độ. Tính năng nén có tổn hao hiệu quả nhất trên những hình ảnh có mật độ điểm ảnh cao, có nhiều nhiễu và màu sắc, thường là ảnh hoặc hình ảnh có nội dung tương tự. Nguyên nhân là do các cấu phần phần mềm tạo ra do quá trình nén có tổn hao ít có khả năng được chú ý hơn trong các hình ảnh chi tiết như vậy. Tuy nhiên, việc nén có tổn hao có thể kém hiệu quả hơn với hình ảnh chứa các cạnh sắc nét như hình vẽ đường nét, các chi tiết rõ ràng tương tự hoặc văn bản. Bạn có thể áp dụng tính năng nén có tổn hao cho hình ảnh JPEG, WebP và AVIF.

Tính năng nén không tổn hao giúp giảm kích thước tệp bằng cách nén hình ảnh mà không làm mất dữ liệu. Tính năng nén không tổn hao mô tả một pixel dựa trên sự khác biệt so với các pixel lân cận. Tính năng nén không tổn hao được dùng cho các định dạng hình ảnh GIF, PNG, WebP và AVIF.

Bạn có thể nén hình ảnh bằng cách sử dụng Squoosh, ImageOptim hoặc một dịch vụ tối ưu hoá hình ảnh. Khi nén, không có chế độ cài đặt chung nào phù hợp cho mọi trường hợp. Bạn nên thử nghiệm nhiều mức nén cho đến khi tìm thấy sự thoả thuận phù hợp giữa chất lượng hình ảnh và kích thước tệp. Một số dịch vụ tối ưu hoá hình ảnh nâng cao có thể tự động làm việc này cho bạn, nhưng có thể không khả thi về mặt tài chính cho tất cả người dùng.

Phần tử <picture>

Phần tử <picture> giúp bạn linh hoạt hơn trong việc chỉ định nhiều hình ảnh đề xuất:

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image.jpg"
  >
</picture>

Khi sử dụng(các) phần tử <source> trong phần tử <picture>, bạn có thể hỗ trợ thêm cho hình ảnh AVIF và WebP, nhưng hãy quay lại sử dụng các định dạng hình ảnh cũ tương thích hơn nếu trình duyệt không hỗ trợ định dạng hiện đại. Với phương pháp này, trình duyệt sẽ chọn phần tử <source> đầu tiên được chỉ định phù hợp. Nếu có thể kết xuất hình ảnh ở định dạng đó, thì trình phân tích cú pháp sẽ sử dụng hình ảnh đó. Nếu không, trình duyệt sẽ chuyển sang phần tử <source> được chỉ định tiếp theo. Trong đoạn mã HTML trước đó, định dạng AVIF được ưu tiên hơn định dạng WebP và quay lại định dạng JPEG nếu không hỗ trợ AVIF hoặc WebP.

Phần tử <picture> cần có phần tử <img> lồng bên trong. Các thuộc tính alt, widthheight được xác định trên <img> và được sử dụng bất kể <source> nào được chọn.

Phần tử <source> cũng hỗ trợ các thuộc tính media, srcsetsizes. Tương tự như ví dụ về <img> trước đó, các khung nhìn này cho trình duyệt biết hình ảnh nào cần chọn trên các khung nhìn khác nhau.

<picture>
  <source
    media="(min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

Thuộc tính mediađiều kiện về nội dung đa phương tiện. Trong ví dụ trước, DPR của thiết bị được dùng làm điều kiện về nội dung đa phương tiện. Mọi thiết bị có DPR lớn hơn hoặc bằng 1,5 sẽ sử dụng phần tử <source> đầu tiên. Phần tử <source> cho trình duyệt biết rằng trên các thiết bị có khung nhìn rộng hơn 768 pixel, hình ảnh đề xuất đã chọn sẽ hiển thị với chiều rộng 500 pixel. Trên các thiết bị nhỏ hơn, kích thước này chiếm toàn bộ chiều rộng của khung nhìn. Bằng cách kết hợp các thuộc tính mediasrcset, bạn có thể kiểm soát tốt hơn hình ảnh nào cần sử dụng.

Điều này được minh hoạ trong bảng sau, trong đó đánh giá một số chiều rộng khung nhìn và tỷ lệ pixel trên thiết bị:

Chiều rộng khung nhìn (pixel) 1 DPR 1,5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 500.jpg 1000.jpg
480 500.jpg 500.jpg 1000.jpg 1500.jpg
560 500.jpg 1000.jpg 1000.jpg 1500.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

Các thiết bị có DPR là 1 sẽ tải hình ảnh image-500.jpg xuống, bao gồm hầu hết người dùng máy tính – những người xem hình ảnh ở kích thước bên ngoài là chiều rộng 500 pixel. Mặt khác, người dùng thiết bị di động có DPR là 3 tải xuống một image-1500.jpg có thể lớn hơn, tương tự như hình ảnh dùng trên thiết bị máy tính có DPR là 3.

<picture>
  <source
    media="(min-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <source
    media="(max-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

Trong ví dụ này, phần tử <picture> được điều chỉnh để bao gồm một phần tử <source> bổ sung nhằm sử dụng nhiều hình ảnh cho các thiết bị rộng có DPR cao:

Chiều rộng khung nhìn (pixel) 1 DPR 1,5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 500.jpg 1000-sm.jpg
480 500.jpg 500.jpg 1000-sm.jpg 1500-sm.jpg
560 500.jpg 1000-sm.jpg 1000-sm.jpg 1500-sm.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

Với truy vấn bổ sung này, bạn có thể thấy image-1000-sm.jpgimage-1500-sm.jpg đang hiển thị trên các khung nhìn nhỏ. Thông tin bổ sung này cho phép bạn nén hình ảnh thêm, vì các cấu phần phần mềm nén không hiển thị nhiều ở kích thước và mật độ đó, đồng thời không ảnh hưởng đến chất lượng hình ảnh trên thiết bị máy tính.

Ngoài ra, bằng cách điều chỉnh các thuộc tính srcsetmedia, bạn có thể tránh phân phát hình ảnh lớn trên khung nhìn nhỏ:

<picture>
  <source
    media="(min-width: 560px)"
    srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
  >
  <source
    media="(max-width: 560px)"
    srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

Trong đoạn mã HTML trước đó, các chỉ số mô tả chiều rộng đã bị xoá và thay vào đó là trình mô tả tỷ lệ pixel của thiết bị. Hình ảnh phân phát trên thiết bị di động chỉ được giới hạn ở /image-500.jpg hoặc /image-1000.jpg, ngay cả trên các thiết bị có DPR là 3.

Cách quản lý sự phức tạp

Khi làm việc với hình ảnh thích ứng, bạn có thể thấy nhiều biến thể kích thước và định dạng khác nhau cho mỗi hình ảnh. Trong ví dụ trước, hệ thống sử dụng các biến thể cho từng kích thước, nhưng loại trừ AVIF và WebP. Bạn nên có bao nhiêu biến thể? Giống như nhiều vấn đề kỹ thuật, câu trả lời thường là " còn tùy".

Mặc dù có thể bạn muốn có nhiều biến thể để cung cấp kết quả phù hợp nhất, nhưng mỗi biến thể hình ảnh bổ sung đều có chi phí và khiến việc sử dụng bộ nhớ đệm của trình duyệt kém hiệu quả hơn. Chỉ với một biến thể, mọi người dùng sẽ nhận được cùng một hình ảnh, nhờ đó, hình ảnh đó có thể được lưu vào bộ nhớ đệm rất hiệu quả.

Mặt khác, nếu có nhiều biến thể, mỗi biến thể sẽ yêu cầu một mục nhập bộ nhớ đệm khác. Chi phí máy chủ có thể tăng và làm giảm hiệu suất nếu mục nhập bộ nhớ đệm của biến thể đã hết hạn và hình ảnh cần được tìm nạp lại từ máy chủ gốc.

Ngoài ra, kích thước tài liệu HTML của bạn tăng lên theo mỗi biến thể. Bạn có thể thấy mình đang vận chuyển nhiều kilobyte HTML cho mỗi hình ảnh.

Phân phát hình ảnh dựa trên tiêu đề của yêu cầu Accept

Tiêu đề của yêu cầu HTTP Accept thông báo cho máy chủ biết loại nội dung mà trình duyệt của người dùng hiểu được. Máy chủ của bạn có thể sử dụng thông tin này để phân phát định dạng hình ảnh tối ưu mà không cần bổ sung thêm byte vào phản hồi HTML.

if (request.headers.accept) {
  if (request.headers.accept.includes('image/avif')) {
    return reply.from('image.avif');
  } else if (request.headers.accept.includes('image/webp')) {
    return reply.from('image.webp');
  }
}

return reply.from('image.jpg');

Đoạn mã HTML trước đó là phiên bản đơn giản của mã mà bạn có thể thêm vào phần phụ trợ JavaScript của máy chủ để chọn và phân phát định dạng hình ảnh tối ưu. Nếu tiêu đề Accept của yêu cầu bao gồm image/avif, thì hình ảnh AVIF sẽ được phân phát. Ngược lại, nếu tiêu đề Accept bao gồm image/webp, thì hình ảnh WebP sẽ được phân phát. Nếu không có điều kiện nào trong số này đúng, thì hình ảnh JPEG sẽ được phân phát.

Bạn có thể sửa đổi phản hồi dựa trên nội dung của tiêu đề yêu cầu Accept trên hầu hết mọi loại máy chủ web, ví dụ: bạn có thể ghi lại yêu cầu hình ảnh trên máy chủ Apache dựa trên tiêu đề Accept bằng cách sử dụng mod_rewrite.

Điều này không giống như hành vi bạn thấy trên Mạng phân phối nội dung hình ảnh (CDN). CDN hình ảnh là giải pháp hiệu quả để tối ưu hoá hình ảnh và gửi định dạng tối ưu dựa trên thiết bị và trình duyệt của người dùng.

Điều quan trọng là phải tìm được sự cân bằng, tạo số lượng hình ảnh đề xuất hợp lý và đo lường tác động đến trải nghiệm người dùng. Các hình ảnh khác nhau có thể mang lại kết quả riêng và mức tối ưu hoá được áp dụng cho từng hình ảnh phụ thuộc vào kích thước của hình ảnh trên trang và thiết bị mà người dùng đang sử dụng. Ví dụ: hình ảnh chính có chiều rộng đầy đủ có thể yêu cầu nhiều biến thể hơn so với hình thu nhỏ trên trang danh sách sản phẩm thương mại điện tử.

Tải từng phần

Bạn có thể yêu cầu trình duyệt tải từng phần của hình ảnh khi những hình ảnh đó xuất hiện trong khung nhìn bằng cách sử dụng thuộc tính loading. Giá trị thuộc tính của lazy yêu cầu trình duyệt không tải hình ảnh xuống cho đến khi hình ảnh đó nằm trong (hoặc gần) khung nhìn. Việc này giúp tiết kiệm băng thông, cho phép trình duyệt ưu tiên các tài nguyên cần thiết để kết xuất nội dung quan trọng đã có trong khung nhìn.

decoding

Thuộc tính decoding cho trình duyệt biết cách giải mã hình ảnh. Giá trị async cho trình duyệt biết rằng hình ảnh có thể được giải mã không đồng bộ, có thể giúp cải thiện thời gian hiển thị nội dung khác. Giá trị của sync cho trình duyệt biết rằng hình ảnh cần hiển thị cùng lúc với nội dung khác. Giá trị mặc định của auto cho phép trình duyệt quyết định giá trị phù hợp nhất với người dùng.

Bản minh hoạ hình ảnh

Kiểm tra kiến thức

Định dạng hình ảnh nào hỗ trợ nén không mất dữ liệu?

Ảnh GIF.
Chính xác!
JPEG.
Hãy thử lại.
PNG.
Chính xác!
WebP.
Chính xác!
AVIF.
Chính xác!

Những định dạng hình ảnh nào hỗ trợ chức năng nén đàn hồi?

Ảnh GIF.
Hãy thử lại. Mặc dù định dạng GIF chỉ hỗ trợ bảng màu giới hạn gồm 256 màu, nhưng bạn phải mã hoá dữ liệu có tổn hao trước khi chuyển đổi sang GIF.
JPEG.
Chính xác!
PNG.
Hãy thử lại.
WebP.
Chính xác!
AVIF.
Chính xác!

Chỉ số mô tả chiều rộng (ví dụ: 1000w) cho trình duyệt biết điều gì về đề xuất hình ảnh được chỉ định trong thuộc tính srcset?

Chiều rộng bên ngoài của hình ảnh, tức là kích thước của hình ảnh trong bố cục sau khi áp dụng kiểu cho trang
Hãy thử lại.
Chiều rộng hàm nội tại của hình ảnh, tức là kích thước của chính hình ảnh.
Chính xác!

Thuộc tính sizes cho trình duyệt biết về phần tử <img> áp dụng thuộc tính này?

Logic biểu thị đề xuất nào được chỉ định trong srcset của phần tử <img> sẽ được tải, dựa trên kích thước của khung nhìn hiện tại của người dùng.
Chính xác!
Chiều rộng nội tại của hình ảnh sẽ được tải từ thuộc tính srcset của phần tử <img>.
Hãy thử lại.

Tiếp theo: Hiệu suất video

Mặc dù hình ảnh có thể là loại nội dung đa phương tiện phổ biến nhất được sử dụng trên web, nhưng chúng không phải là loại nội dung duy nhất bạn cần lưu ý khi nói đến hiệu suất. Video là một loại nội dung nghe nhìn phổ biến khác được sử dụng trên web và cũng cần những yếu tố riêng biệt về hiệu suất. Trong mô-đun tiếp theo của khoá học này, hãy khám phá một số kỹ thuật giúp tối ưu hoá video và cách tải video hiệu quả.