Các tính năng mới trong chỉ thị Angular NgOptimizedImage

Alex Castle
Alex Castle

Chỉ hơn một năm trước, nhóm Chrome Aurora đã ra mắt lệnh Angular NgOptimizedImage. Chỉ thị này chủ yếu tập trung vào việc cải thiện hiệu suất thông qua các chỉ số Core Web Vitals. API này kết hợp các phương pháp tối ưu hoá phổ biến và các phương pháp hay nhất cho hình ảnh vào một API dành cho người dùng mà không phức tạp hơn nhiều so với phần tử <img> tiêu chuẩn.

Vào năm 2023, chúng tôi đã cải thiện chỉ thị này bằng các tính năng mới. Bài đăng này mô tả quan trọng nhất trong số các tính năng mới đó, nhấn mạnh lý do chúng tôi chọn ưu tiên mỗi tính năng và cách tính năng này có thể giúp cải thiện hiệu suất của các ứng dụng Angular.

Tính năng mới

NgOptimizedImage đã cải thiện đáng kể theo thời gian, bao gồm các tính năng mới sau đây.

Chế độ tô màu nền

Việc định kích thước hình ảnh bằng cách cung cấp thuộc tính widthheight là một phương pháp tối ưu hoá cực kỳ quan trọng để giảm tình trạng thay đổi bố cục, vì trình duyệt cần biết tỷ lệ khung hình của hình ảnh để tiết kiệm không gian lưu trữ. Tuy nhiên, việc định cỡ hình ảnh là một công việc bổ sung đối với các nhà phát triển ứng dụng và không phù hợp trong một số trường hợp sử dụng hình ảnh.

Giúp giải quyết vấn đề căng thẳng này là tính năng chính đầu tiên được thêm vào bản xem trước của thành phần hình ảnh sau khi nhà phát triển sử dụng: chế độ lấp đầy. Đây là cách để nhà phát triển thêm hình ảnh mà không cần định kích thước rõ ràng và không làm ảnh hưởng đến bố cục.

Ở chế độ lấp đầy, yêu cầu về kích thước hình ảnh sẽ bị tắt và hình ảnh sẽ được tự động tạo kiểu để lấp đầy phần tử chứa hình ảnh. Cách này tách riêng tỷ lệ khung hình của hình ảnh với không gian mà hình ảnh chiếm trên trang, đồng thời giúp bạn có nhiều quyền kiểm soát hơn đối với việc hình ảnh vừa với bố cục trang như thế nào.

Chế độ tô màu nền sử dụng NgOptimizedImage làm giải pháp thay thế hiệu quả hơn cho thuộc tính css background-image. Đặt một hình ảnh bên trong <div> hoặc phần tử khác lẽ ra có kiểu background-image, sau đó bật chế độ tô màu nền, như minh hoạ trong đoạn mã ví dụ trước. Sử dụng thuộc tính CSS object-fitobject-position trên <div> để kiểm soát cách hình ảnh được định vị ở chế độ nền.

// Height and width are required
<img ngSrc="example.com" height="300" width="400">

// Unless you use fill mode!
<div style="width: 100vw; height: 50em; position: relative">
  <img ngSrc="example.com" fill>
</div>

Tạo Srcset

Một trong những kỹ thuật tối ưu hoá hình ảnh hiệu quả nhất là sử dụng thuộc tính srcset để đảm bảo tải hình ảnh có kích thước phù hợp xuống cho mọi thiết bị truy cập vào ứng dụng của bạn. Việc sử dụng srcset trên toàn bộ ứng dụng có thể giúp bạn không lãng phí băng thông và cải thiện đáng kể Chỉ số quan trọng chính của trang web LCP.

Nhược điểm của thuộc tính srcset là có thể rườm rà khi triển khai. Bạn có thể viết các giá trị srcset theo cách thủ công, tức là thêm nhiều dòng đánh dấu vào mỗi phần tử hình ảnh trong ứng dụng, hoàn thiện bằng nhiều URL tuỳ chỉnh cho mỗi srcset. Bạn cũng phải quyết định một tập hợp các điểm ngắt phức tạp vì chúng có thể đại diện cho cả mật độ màn hình và kích thước khung nhìn của các thiết bị phổ biến.

Đó là lý do việc thêm tính năng tạo srcset tự động vào lệnh NgOptimizedImage là một mốc quan trọng sau khi ra mắt. Nhờ vậy, mọi ứng dụng sử dụng CDN hỗ trợ đổi kích thước hình ảnh đều có thể nhận được các phần tử srcset đầy đủ, có thể tuỳ chỉnh và tự động được thêm vào mọi hình ảnh được tạo bằng lệnh NgOptimizedImage.

Chúng tôi đã thêm một API đơn giản để đặt thuộc tính sizes. API này dùng để đảm bảo rằng mỗi hình ảnh đều nhận đúng loại srcset. Nếu bạn không thêm thuộc tính sizes, chúng ta sẽ biết rằng hình ảnh dành cho kích thước cố định và sẽ nhận được một thuộc tính srcset phụ thuộc vào mật độ, như sau:

<img src="www.example.com/image.png" srcset="www.example.com/image.png?w=400 1x, www.example.com/image.png?w=800 2x" >

Loại srcset này đảm bảo hình ảnh được phân phát ở kích thước có tính đến mật độ pixel trên thiết bị của người dùng.

Mặt khác, nếu bạn thêm thuộc tính sizes, NgOptimizedImage sẽ tạo một srcset thích ứng bao gồm các điểm ngắt cho nhiều kích thước hình ảnh và thiết bị phổ biến, sử dụng danh sách điểm ngắt mặc định sau:

[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]

Tạo kết nối trước

Để cải thiện LCP, bạn cần giảm thời gian mà người dùng bỏ ra để tải hình ảnh LCP xuống. Trong phần trước, bạn đã biết cách srcset có thể hỗ trợ việc chuyển các tệp hình ảnh nhỏ hơn. Tuy nhiên, một điểm tối ưu hoá quan trọng không kém là bắt đầu chuyển càng sớm càng tốt. Một cách để thực hiện việc này là sử dụng thẻ link rel="preconnect" để bắt đầu kết nối với miền hình ảnh của bạn.

Ngay từ đầu, NgOptimizedImage cảnh báo nếu bạn không kết nối trước được với miền của hình ảnh LCP, nhưng cảnh báo không phải là giải pháp lý tưởng – chúng tôi chỉ muốn khắc phục vấn đề cho bạn. Và đó chính là những gì mà NgOptimizedImage hiện đang làm, với tính năng tạo kết nối trước tự động.

Để hỗ trợ tính năng này, chúng tôi sử dụng quy trình phân tích mã tĩnh nhằm cố gắng phát hiện miền hình ảnh trong trình tải NgOptimizedImage và tự động tạo thẻ liên kết kết nối trước cho các miền đó. Trong một số trường hợp, người dùng vẫn cần phải có đường liên kết kết nối trước theo cách thủ công, nhưng đối với hầu hết người dùng, việc tự động kết nối trước giúp giảm bớt một bước cần thiết để hình ảnh đạt được hiệu suất cao.

Tính năng hỗ trợ nâng cao cho trình tải tuỳ chỉnh

Một thành phần chính của NgOptimizedImage là cấu trúc trình tải, cho phép lệnh này tự động tạo các URL phù hợp với CDN hình ảnh của ứng dụng. Một bộ trình tải tích hợp sẵn đi kèm cho các CDN được sử dụng rộng rãi. Chúng tôi cũng cho phép bạn sử dụng trình tải tuỳ chỉnh, giúp bạn tích hợp NgOptimizedImage với hầu hết mọi giải pháp lưu trữ hình ảnh.

Khi ra mắt, các trình tải tuỳ chỉnh này chỉ hoạt động trong phạm vi giới hạn và chỉ có thể đọc thuộc tính width từ phần tử hình ảnh. Để đáp lại ý kiến phản hồi của người dùng, chúng tôi đã hỗ trợ thêm cấu trúc dữ liệu loaderParams có thể tuỳ chỉnh. Cấu trúc này cho phép truyền dữ liệu tuỳ ý từ phần tử hình ảnh đến trình tải tuỳ chỉnh. Với việc mở rộng này, trình tải tuỳ chỉnh có thể đơn giản hoặc phức tạp theo yêu cầu của cơ sở hạ tầng hình ảnh của ứng dụng.

Ví dụ sau đây cho thấy cách một trình tải tuỳ chỉnh đơn giản có thể sử dụng API loaderParams để chọn giữa hai miền hình ảnh thay thế:

const myCustomLoader = (config: ImageLoaderConfig) => {
  if (config.loaderParams?.alternateDomain) {
    return `https://alternate.domain.com/images/${config.src}`
  }
  return `https://primary.domain.com/images/${config.src}`;
};

Bạn có thể xem ví dụ về trình tải tuỳ chỉnh phức tạp hơn trong tài liệu về Angular.

Hướng dẫn mở rộng về hiệu suất của hình ảnh

Cho đến nay, mọi cảnh báo về hiệu suất hình ảnh mà chúng tôi thêm vào Angular đều nằm trong lệnh NgOptimizedImage. Nếu không dùng lệnh này trong ứng dụng, bạn sẽ không nhận được hướng dẫn nào về các vấn đề liên quan đến hiệu suất của hình ảnh.

Trong Angular 17, chúng tôi sẽ mở rộng phạm vi hướng dẫn về hiệu suất hình ảnh để bao gồm tất cả các ứng dụng Angular. Giờ đây, nếu phát hiện các mẫu hình ảnh mà chúng tôi biết là nhầm lẫn gây ảnh hưởng xấu đến hiệu suất, chẳng hạn như tải từng phần hình ảnh LCP hoặc tải xuống một tệp quá lớn đối với trang, chúng tôi sẽ thông báo cho bạn biết, ngay cả khi bạn không sử dụng NgOptimizedImage.

Hiệu suất hình ảnh là yếu tố quan trọng đối với tất cả ứng dụng, và chúng tôi rất vui mừng được tiếp tục xây dựng những biện pháp giúp ngăn chặn những lỗi thường gặp trong ứng dụng Angular.

Hướng đến tương lai

Chúng tôi đã nỗ lực phát triển bộ tính năng tiếp theo cho NgOptimizedImage. Mặc dù hiệu suất hình ảnh vẫn là mối quan tâm chính của chúng tôi, nhưng chúng tôi cũng muốn thêm các tính năng giúp cải thiện trải nghiệm của nhà phát triển, để đảm bảo rằng NgOptimizedImage luôn là một lựa chọn hấp dẫn để đưa hình ảnh vào các ứng dụng Angular.

Một tính năng được chúng tôi ưu tiên là phần giữ chỗ hình ảnh. Các quy tắc này thường được dùng để giúp hình ảnh tải trông đẹp hơn trên các ứng dụng web, nhưng có thể làm giảm hiệu suất nếu được triển khai không đúng cách. Chúng tôi hy vọng xây dựng được một hệ thống phần giữ chỗ hình ảnh ưu tiên hiệu suất cho NgOptimizedImage. Hãy theo dõi blog của chúng tôi để biết thêm thông báo!