Vào tháng 5 năm 2022, nhóm Aurora và Angular thông báo rằng họ sẽ cộng tác để triển khai chỉ thị về hình ảnh cho Angular. Gần đây, chúng tôi đã phát hành hướng dẫn này cho bản dùng thử dành cho nhà phát triển trong Angular phiên bản 14.2. Bài đăng này trình bày cách lệnh hình ảnh mới, NgOptimizedImage
, hỗ trợ tối ưu hoá hình ảnh trong Angular.
Thông tin khái quát
Hình ảnh là một thành phần phổ biến và quan trọng trong trải nghiệm người dùng trên web, với 99,9% trang web tạo ra yêu cầu cho một hoặc nhiều hình ảnh. Hình ảnh cũng là yếu tố đóng góp đáng kể nhất vào kích thước trang, chiếm trung bình 982 kilobyte mỗi trang.
Do số lượng và kích thước ngày càng tăng, hình ảnh có thể cản trở hiệu suất của trang web và ảnh hưởng đến các chỉ số Các chỉ số quan trọng về trang web. Đối với 79,4% trang dành cho máy tính, hình ảnh là phần tử Thời gian hiển thị nội dung lớn nhất (LCP) trong năm 2021. Do đó, việc theo đuổi hình ảnh được tối ưu hoá đã trở thành một nỗ lực không ngừng của nhiều người.
Nhóm Aurora tin tưởng vào việc tận dụng sức mạnh của các khung để cung cấp các giải pháp tích hợp sẵn cho các thách thức thường gặp của nhà phát triển. Bước đầu tiên của họ trong lĩnh vực tối ưu hoá hình ảnh là thành phần hình ảnh Next.js. Họ coi thành phần này là một nền tảng thử nghiệm để xem việc cải thiện trải nghiệm nhà phát triển (DX) về việc tối ưu hoá hình ảnh có thể giúp tăng hiệu suất cho nhiều ứng dụng sử dụng khung hơn hay không.
Nhóm kết quả đầu tiên từ người dùng Next.js Leboncoin rất đáng khích lệ. Leboncoin đã cải thiện đáng kể chỉ số LCP (từ 2,4 giây xuống còn 1,7 giây) sau khi bắt đầu sử dụng next/image
. Việc sử dụng next/image
sau đó trong cộng đồng đã góp phần làm tăng số lượng gốc Next.js đáp ứng ngưỡng LCP. Chẳng bao lâu sau, đã có yêu cầu về các tính năng tương tự trong các khung khác, một trong số đó là Angular.
Do đó, Aurora đã tham khảo ý kiến của Angular và Nuxt để tạo nguyên mẫu thành phần hình ảnh cho các khung này. Thành phần hình ảnh Nuxt được phát hành vào năm ngoái. Hiện tại, lệnh hình ảnh Angular (NgOptimizedImage
) đã được phát hành để đưa các chế độ tối ưu hoá hình ảnh mặc định sang Angular.
Cơ hội
Angular là một trong những khung JavaScript hàng đầu được các nhà phát triển sử dụng hiện nay. Hơn 50 nghìn nguồn gốc được HTTPArchive thu thập thông tin trên thiết bị di động và có gần 3 triệu lượt tải xuống hằng tuần trên NPM.
Khi xem xét điểm số của Chỉ số quan trọng chính của trang web, tỷ lệ phần trăm các nguồn gốc Angular đáp ứng ngưỡng LCP "tốt" vẫn cần được cải thiện. Chỉ 18,74% trang web Angular có LCP tốt trên thiết bị di động vào tháng 6 năm 2022. Vì hình ảnh là phần tử LCP của hơn 70% trang web trên thiết bị di động và máy tính, nên hình ảnh LCP chưa được tối ưu hoá có thể là một trong những nguyên nhân chính khiến LCP kém hơn trên các trang web Angular.
Chỉ thị hình ảnh Angular được thiết kế để giúp cải thiện những con số này.
MVP cho chỉ thị NgOptimizedImage
MVP của lệnh hình ảnh Angular được xây dựng dựa trên những bài học từ các thành phần hình ảnh mà Aurora đã xây dựng cho đến nay trong khi điều chỉnh thiết kế cho phù hợp với trải nghiệm kết xuất phía máy khách của Angular. Nhiều vấn đề tối ưu hoá hình ảnh tiêu chuẩn đã được giải quyết bằng cách:
- Cung cấp giá trị mặc định mạnh.
- Gửi lỗi hoặc cảnh báo để đảm bảo tuân thủ các phương pháp hay nhất.
Sau đây là những điểm nổi bật của thiết kế:
Tải từng phần thông minh
Hình ảnh mà người dùng không nhìn thấy khi tải trang (ví dụ: hình ảnh bên dưới màn hình đầu tiên hoặc hình ảnh băng chuyền bị ẩn) nên được tải lười. Tính năng tải lười giải phóng tài nguyên trình duyệt để tải văn bản, nội dung nghe nhìn hoặc tập lệnh quan trọng khác. Hầu hết hình ảnh không quan trọng và nên được tải lười, nhưng chỉ 7,8% số trang sử dụng tính năng tải lười gốc trong năm 2021.
Theo mặc định, lệnh hình ảnh Angular tải lười hình ảnh không quan trọng và chỉ tải nhanh hình ảnh được đánh dấu đặc biệt là
priority
. Điều này đảm bảo hầu hết hình ảnh đều có hành vi tải tối ưu.Ưu tiên hình ảnh quan trọng
Thêm gợi ý về tài nguyên (ví dụ:
preload
hoặcpreconnect
) để ưu tiên tải các hình ảnh quan trọng là một phương pháp hay nhất được đề xuất. Tuy nhiên, hầu hết các ứng dụng đều không dùng đến những phần tử này. Theo Web Almanac 2021, chỉ 12,7% số trang dành cho thiết bị di động sử dụng gợi ý kết nối trước và chỉ 22,1% số trang dành cho thiết bị di động sử dụng gợi ý tải trước.Chỉ thị hình ảnh hoạt động trên hai mặt khi hình ảnh được đánh dấu là ưu tiên.
- Phương thức này đặt fetchpriority của hình ảnh thành
"high"
để trình duyệt biết rằng nó phải tải hình ảnh xuống với mức độ ưu tiên cao. - Ở chế độ phát triển, quy trình kiểm tra thời gian chạy xác nhận rằng gợi ý tài nguyên
preconnect
đã được đưa vào tương ứng với nguồn gốc của hình ảnh.
Ở chế độ phát triển, lệnh này cũng sử dụng PerformanceObserver API để xác minh rằng hình ảnh LCP đã được đánh dấu là
priority
như dự kiến. Nếu không được đánh dấu làpriority
, hệ thống sẽ gửi một lỗi hướng dẫn nhà phát triển thêm thuộc tínhpriority
vào hình ảnh LCP.Cuối cùng, sự kết hợp giữa tính năng tự động hoá và tuân thủ này đảm bảo rằng hình ảnh LCP có gợi ý
preconnect
, giá trị thuộc tínhfetchpriority
làhigh
và không được tải lười.- Phương thức này đặt fetchpriority của hình ảnh thành
Cấu hình được tối ưu hoá cho các công cụ xử lý hình ảnh phổ biến
Các ứng dụng Angular nên sử dụng CDN hình ảnh, thường cung cấp dịch vụ tối ưu hoá theo mặc định.
Chỉ thị này khuyến khích nhà phát triển sử dụng CDN hình ảnh bằng cách mang đến trải nghiệm đặc biệt hấp dẫn cho nhà phát triển (DX) để định cấu hình các CDN trong ứng dụng. Lệnh này hỗ trợ một API trình tải cho phép bạn xác định nhà cung cấp CDN và URL cơ sở trong cấu hình của mình. Sau khi định cấu hình, bạn chỉ cần xác định tên thành phần trong mã đánh dấu. Ví dụ:
// in module providers: provideImgixLoader('https://mysite.net/assets/') // in markup <img ngSrc="image.png" > <img ngSrc="image2.png" >
Điều này tương đương với việc thêm các thẻ hình ảnh sau và giảm lượng mã đánh dấu mà nhà phát triển phải thêm cho mỗi hình ảnh.
<img src="https://mysite.net/assets/image.png"> <img src="https://mysite.net/assets/image2.png">
Chỉ thị hình ảnh cung cấp trình tải tích hợp sẵn với cấu hình tối ưu cho các CDN hình ảnh phổ biến nhất. Các trình tải này sẽ tự động định dạng URL hình ảnh để đảm bảo rằng bạn sử dụng chế độ cài đặt nén và định dạng hình ảnh được đề xuất cho từng CDN.
Lỗi và cảnh báo tích hợp sẵn
Ngoài các tính năng tối ưu hoá tích hợp sẵn ở trên, lệnh này cũng có các bước kiểm tra tích hợp để đảm bảo rằng nhà phát triển đã tuân theo các phương pháp hay nhất được đề xuất về mã đánh dấu hình ảnh. Chỉ thị hình ảnh thực hiện các bước kiểm tra sau.
Hình ảnh chưa có kích thước: Lệnh hình ảnh sẽ báo lỗi nếu mã đánh dấu hình ảnh không xác định chiều rộng và chiều cao rõ ràng. Hình ảnh chưa được định cỡ có thể gây ra thay đổi bố cục, ảnh hưởng đến chỉ số Mức thay đổi bố cục tích luỹ (CLS) của trang. Phương pháp hay nhất được đề xuất để ngăn chặn điều này là hình ảnh phải có các thuộc tính
width
vàheight
được chỉ định.Tỷ lệ khung hình: Chỉ thị hình ảnh sẽ gửi một lỗi để cho nhà phát triển biết nếu tỷ lệ khung hình của
width
:height
được xác định trong HTML không gần với tỷ lệ khung hình thực tế của hình ảnh đã kết xuất. Điều này có thể khiến hình ảnh bị méo trên màn hình. Điều này có thể xảy ra nếu- Bạn đã xác định sai kích thước (chiều rộng hoặc chiều cao) do nhầm lẫn hoặc
- Nếu bạn đã xác định một kích thước theo tỷ lệ phần trăm trong CSS nhưng không xác định kích thước còn lại (ví dụ:
width: 100%
cầnheight: auto
để đảm bảo hình ảnh tăng theo cả hai kích thước).
Hình ảnh quá khổ: Nếu hình ảnh không xác định
srcset
và hình ảnh nội tại lớn hơn đáng kể so với hình ảnh được kết xuất, thì lệnh này sẽ hiển thị cảnh báo đề xuất sử dụng các thuộc tínhsrcset
vàsizes
.Mật độ hình ảnh: Chỉ thị này sẽ gửi lỗi nếu bạn cố gắng đưa một hình ảnh vào
srcset
có mật độ điểm ảnh lớn hơn3x
. Bạn thường không nên sử dụng các chỉ số mô tả cao hơn2x
vì điều này có thể dẫn đến hậu quả ngoài mong muốn là buộc các thiết bị di động có độ phân giải cao phải tải hình ảnh khổng lồ xuống. Hơn nữa, mắt người thực sự không thể phân biệt được nhiều sự khác biệt khi tỷ lệ trên 2x.
Thử thách
Việc điều chỉnh các chiến lược tối ưu hoá hình ảnh để hoạt động trong khung phía máy khách là thách thức chính khi thiết kế NgOptimizedImage
. Trải nghiệm hiển thị mặc định trên Next.js là Kết xuất phía máy chủ (SSR) hoặc Tạo trang web tĩnh (SSG), trong khi trên Angular là Kết xuất phía máy khách (CSR). Mặc dù Angular hỗ trợ thư viện SSR – góc/phổ thông – nhưng hầu hết ứng dụng Angular (~60%) đều sử dụng CSR.
Lệnh hình ảnh được xây dựng hoàn toàn cho CSR để phù hợp với trường hợp sử dụng thông thường trong các ứng dụng Angular. Điều này đặt ra thêm các quy tắc ràng buộc và nhóm phải suy nghĩ lại về cách xây dựng các phương pháp tối ưu hoá cụ thể cho các ứng dụng CSR.
Bạn gặp phải một số thách thức như sau:
Hỗ trợ gợi ý tài nguyên
Tính năng tải trước các thành phần quan trọng giúp trình duyệt phát hiện các thành phần đó sớm hơn. Tuy nhiên, việc đưa gợi ý tài nguyên vào ứng dụng Angular sẽ phức tạp vì:
Thêm theo cách thủ công: Nhà phát triển khó có thể thêm gợi ý tài nguyên
preload
theo cách thủ công. Angular sử dụng một tệp index.html dùng chung cho toàn bộ dự án hoặc cho tất cả các tuyến trong trang web. Do đó,<head>
của tài liệu là giống nhau ở mọi tuyến (ít nhất là tại thời gian cung cấp). Việc thêm bất kỳ gợi ýpreload
nào vào<head>
có nghĩa là tài nguyên sẽ được tải trước cho tất cả các tuyến đường ngay cả khi không bắt buộc. Do đó, bạn không nên thêm gợi ýpreload
theo cách thủ công.Tự động thêm trong quá trình hiển thị: Việc sử dụng khung để thêm gợi ý tải trước vào đầu tài liệu trong quá trình hiển thị trong ứng dụng CSR sẽ không giúp ích gì. Vì quá trình kết xuất xảy ra sau khi JavaScript được tải xuống và thực thi, nên
<head>
sẽ được kết xuất quá muộn để có bất kỳ giá trị nào.Đối với phiên bản đầu tiên của lệnh, sự kết hợp giữa gợi ý
preconnect
và gợi ýfetchpriority
sẽ giúp ưu tiên hình ảnh thay vìpreload
. Tuy nhiên, Aurora hiện đang làm việc với nhóm Angular CLI để bật tính năng chèn tự động gợi ý tài nguyên tại thời điểm tạo bản dựng. Hãy chú ý theo dõi!Tối ưu hoá kích thước và định dạng hình ảnh trên máy chủ
Vì các ứng dụng Angular thường được kết xuất phía máy khách, nên hình ảnh trên hệ thống tệp không thể được nén tại thời điểm yêu cầu và được phân phát nguyên trạng. Vì lý do này, bạn nên sử dụng CDN hình ảnh để nén hình ảnh và chuyển đổi chúng thành các định dạng hiện đại như WebP hoặc AVIF theo yêu cầu.
Mặc dù lệnh này không thực thi việc sử dụng CDN của hình ảnh, nhưng bạn nên sử dụng cùng với lệnh và các trình tải tích hợp sẵn giúp đảm bảo sử dụng đúng tuỳ chọn cấu hình.
Tác động
Bản minh hoạ sau đây cho thấy sự khác biệt mà lệnh hình ảnh Angular có thể tạo ra đối với hiệu suất hình ảnh. Công cụ này so sánh hai trang web:
Trang web 1: Sử dụng các phần tử <img>
gốc có hình ảnh được phân phát thông qua CDN Imgix (với các tuỳ chọn cấu hình mặc định).
Trang web thứ hai: Sử dụng lệnh image cho tất cả hình ảnh. Tệp này cũng bao gồm các biện pháp tối ưu hoá được đề xuất trực tiếp theo cảnh báo hoặc lỗi do lệnh đưa ra.
Nhóm đã làm việc với các đối tác để xác thực tác động của lệnh hình ảnh đối với hiệu suất của các ứng dụng Angular thực tế dành cho doanh nghiệp.
Một trong những đối tác này là Land's End. Dự kiến trang web của họ sẽ là một trường hợp kiểm thử phù hợp cho kết quả mà các ứng dụng thực tế có thể thấy.
Họ đã tiến hành kiểm thử trong phòng thí nghiệm Lighthouse trên môi trường đảm bảo chất lượng trước và sau khi sử dụng lệnh ảnh. Trên máy tính, LCP trung bình của họ giảm từ 12 giây xuống còn 3 giây, tức là cải thiện 75% LCP. Trên thiết bị di động, LCP trung bình giảm từ 20,2 giây xuống 12 giây (cải thiện 40,6%).
Lộ trình trong tương lai
Đây chỉ là phần đầu tiên của thiết kế cho lệnh ảnh Angular. Chúng tôi dự định cung cấp nhiều tính năng khác cho các phiên bản trong tương lai, bao gồm:
Hỗ trợ tốt hơn cho hình ảnh thích ứng:
NgOptimizedImage
hiện hỗ trợ sử dụngsrcset
, nhưng bạn phải cung cấp thuộc tínhsrcset
vàsizes
theo cách thủ công cho từng hình ảnh. Trong tương lai, lệnh này có thể tự động tạo các thuộc tínhsrcset
vàsizes
.Tự động chèn gợi ý tài nguyên
Bạn có thể tích hợp với Angular CLI để tạo thẻ kết nối trước và tải trước cho các hình ảnh LCP quan trọng.
Hỗ trợ Angular SSR
Phiên bản MVP được thiết kế dựa trên các quy tắc ràng buộc của Angular CSR, nhưng bạn cũng cần tìm hiểu các giải pháp tối ưu hoá hình ảnh cho Angular SSR (góc/phổ thông).
Cải tiến trải nghiệm của nhà phát triển
NgOptimizedImage
yêu cầu bạn phải chỉ định thuộc tínhwidth
vàheight
cho mỗi hình ảnh. Tuy nhiên, việc chỉ định các thông số này cho từng hình ảnh có thể gây phiền toái cho một số nhà phát triển. Có thể cải thiện trải nghiệm của nhà phát triển trong lần lặp lại tiếp theo như sau:- Hỗ trợ một chế độ bổ sung (tương tự như tuỳ chọn bố cục hình ảnh "
fill
" trong Next.js) không yêu cầu xác định rõ chiều rộng/chiều cao. - Sử dụng tính năng tích hợp CLI để tự động đặt chiều rộng và chiều cao cho hình ảnh cục bộ bằng cách xác định kích thước thực tế của hình ảnh.
- Hỗ trợ một chế độ bổ sung (tương tự như tuỳ chọn bố cục hình ảnh "
Kết luận
Nhà phát triển sẽ có thể sử dụng lệnh hình ảnh Angular theo từng giai đoạn, bắt đầu từ phiên bản xem trước dành cho nhà phát triển trong phiên bản 14.2.0. Hãy dùng thử NgOptimizedImage
và để lại ý kiến phản hồi!
Xin cảm ơn đặc biệt Katie Hempenius và Alex Castle đã đóng góp cho bài viết này.