מה חדש בהנחיה Angular NgOptimizedImage

Alex Castle
Alex Castle

לפני קצת יותר משנה, צוות Chrome Aurora השיק את ההוראה NgOptimizedImage של Angular. ההוראה מתמקדת בעיקר בשיפור הביצועים, כפי שנמדד על ידי מדדי הליבה לבדיקת חוויית המשתמש באתר. הוא מקבץ שיטות מומלצות ואופטימיזציות נפוצות של תמונות ב-API שגלוי למשתמשים, והוא לא הרבה יותר מורכב מרכיב <img> רגיל.

בשנת 2023 שיפרנו את directive עם תכונות חדשות. בפוסט הזה מתוארות התכונות החדשות המשמעותיות ביותר, עם דגש על הסיבות שבגללן בחרנו לתת עדיפות לכל תכונה, ואיך היא יכולה לעזור לשפר את הביצועים של אפליקציות Angular.

תכונות חדשות

התכונה NgOptimizedImage השתפרה משמעותית עם הזמן, כולל התכונות החדשות הבאות.

מצב מילוי

ציון גודל התמונות על ידי ציון המאפיינים width ו-height הוא אופטימיזציה חשובה ביותר לצמצום השינויים בפריסה, כי דפדפנים צריכים לדעת מהו יחס הגובה-רוחב של התמונה כדי לחסוך מקום. עם זאת, שינוי הגודל של תמונות הוא עבודה נוספת למפתחי האפליקציות, והוא לא הגיוני בחלק מתרחישי השימוש בתמונות.

התכונה העיקרית הראשונה שנוספה לרכיב התמונה אחרי תצוגה מקדימה למפתחים עוזרת לפתור את המתח הזה: מצב מילוי. זוהי דרך למפתחים לכלול תמונות בלי לקבוע את הגודל שלהן באופן מפורש, ובלי לגרום לשינוי בפריסה.

במצב מילוי, הדרישה לשינוי גודל התמונה מושבתת, והתמונה משתנה באופן אוטומטי כך שתמלא את הרכיב שמכיל אותה. כך אפשר לנתק את יחס הגובה-רוחב של התמונה מהמרחב שהיא תופסת בדף, ולשלוט טוב יותר באופן שבו התמונות משתלבות בפריסת הדף.

במצב מילוי, המערכת משתמשת ב-NgOptimizedImage כחלופה עם ביצועים טובים יותר למאפיין ה-CSS background-image. ממוקמים תמונה בתוך <div> או באלמנט אחר שהיה צריך להיות לו סגנון background-image, ואז מפעילים את מצב המילוי, כפי שמוצג בדוגמת הקוד שלמעלה. כדי לקבוע את מיקום התמונה ברקע, משתמשים במאפייני ה-CSS object-fit ו-object-position ב-<div>.

// 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>

יצירת קובצי srcset

אחת מהשיטות היעילות ביותר לביצוע אופטימיזציה של תמונות היא שימוש במאפיין srcset כדי להבטיח שתתבצע הורדה של תמונות בגודל המתאים לכל מכשיר שמקבל גישה לאפליקציה. שימוש ב-srcset בכל האפליקציה יכול למנוע בזבוז של רוחב פס ולשפר באופן משמעותי את מדד LCP של המדדים הבסיסיים של חוויית המשתמש (Core Web Vitals).

החיסרון של המאפיין srcset הוא שהטמעתו עשויה להיות מסורבלת. כשמעיינים בערכים של srcset באופן ידני, צריך להוסיף כמה שורות של רכיבי Markup לכל רכיב תמונה באפליקציה, יחד עם כמה כתובות URL בהתאמה אישית לכל srcset. בנוסף, צריך להחליט על קבוצה של נקודות עצירה. זהו תהליך מורכב, כי הנקודות האלה יכולות לייצג גם את צפיפות המסך וגם את גדלי חלון התצוגה של מכשירים נפוצים.

לכן, הוספת יצירה אוטומטית של srcset להנחיה NgOptimizedImage הייתה אבן דרך חשובה אחרי ההשקה. בעזרת התוספת הזו, כל אפליקציה שמשתמשת ב-CDN שתומך בשינוי גודל של תמונות יכולה לקבל באופן אוטומטי srcsets מלאים ומותאמים אישית לכל תמונה שנוצרת באמצעות ההנחיה NgOptimizedImage.

כללנו API פשוט יותר להגדרת המאפיין sizes, שנועד להבטיח שכל תמונה תקבל את הסוג הנכון של srcset. אם לא תכללו את המאפיין sizes, נדע שהתמונה אמורה להיות בגודל קבוע, וצריך להגדיר לה srcset שמבוסס על צפיפות, כמו הדוגמה הבאה:

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

סוג srcset כזה מבטיח שהתמונות יוצגו בגודל שמביא בחשבון את דחיסות הפיקסלים של המכשיר של המשתמש.

לעומת זאת, אם תכללו את המאפיין sizes, NgOptimizedImage ייצור srcset רספונסיבי שכולל נקודות עצירה רבות למכשירים ולגדלים נפוצים של תמונות, באמצעות רשימת ברירת המחדל הזו של נקודות עצירה:

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

יצירת חיבור מראש

כדי לשפר את ה-LCP, חשוב לצמצם את הזמן שהמשתמשים מקדישים להורדת תמונת ה-LCP. בקטע הקודם ראינו איך srcset יכול לעזור בהעברת קובצי תמונות קטנים יותר, אבל אופטימיזציה חשובה לא פחות היא להתחיל את ההעברה בהקדם האפשרי. אחת הדרכים לעשות זאת היא להשתמש בתגי link rel="preconnect" כדי להתחיל את החיבור לדומיין התמונות.

כבר מההתחלה, המערכת של NgOptimizedImage הזהירה אם לא ביצעתם חיבור מראש לדומיין של קובץ האימג' של LCP, אבל אזהרה היא לא הפתרון האידיאלי – אנחנו מעדיפים פשוט לפתור את הבעיה בשבילכם. וזה בדיוק מה ש-NgOptimizedImage עושה עכשיו, באמצעות יצירה אוטומטית של חיבור מראש.

כדי לתמוך בתכונה הזו, אנחנו משתמשים בניתוח קוד סטטי כדי לנסות לזהות דומיינים של תמונות במטענים של NgOptimizedImage, וליצור באופן אוטומטי תגי קישור של חיבור מראש לדומיינים האלה. עדיין יכולים להיות מקרים שבהם נדרשים קישורים מקדימים ידניים, אבל עבור רוב המשתמשים, חיבור מראש אוטומטי מאפשר להם להשיג ביצועים טובים יותר של התמונות בלי לבצע שלב נוסף.

תמיכה משופרת בתוכנות טעינה בהתאמה אישית

אחד מהרכיבים העיקריים של NgOptimizedImage הוא ארכיטקטורת הטעינה, שמאפשרת להנחיה ליצור באופן אוטומטי כתובות URL שמותאמות ל-CDN של התמונות של האפליקציה. כלולה קבוצה של מטענים מובנים עבור רשתות CDN שנמצאות בשימוש נרחב. אנחנו גם מספקים אפשרות להשתמש במטענים מותאמים אישית, שמאפשרים לשלב את NgOptimizedImage כמעט בכל פתרון לאירוח תמונות.

בזמן ההשקה, היקף הטעינה המותאם אישית היה מוגבל, והוא יכול היה לקרוא רק את המאפיין width מרכיב התמונה. בתגובה למשוב מהמשתמשים, הוספנו תמיכה במבנה נתונים loaderParams שניתן להתאמה אישית, שמאפשר להעביר נתונים שרירותיים מרכיב התמונה למטען הנתונים המותאם אישית. לאחר ההרחבה, מטענים מותאמים אישית יכולים להיות פשוטים או מורכבים, כפי שנדרש על ידי תשתית התמונה של האפליקציה.

הדוגמה הבאה מראה איך טוען מותאם אישית פשוט יכול להשתמש ב-API loaderParams כדי לבחור בין שני דומיינים חלופיים של תמונות:

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

דוגמה למטען מותאם אישית מורכב יותר זמינה במסמכי התיעוד של Angular.

הנחיות מורחבות לביצועי התמונות

עד עכשיו, כל התראות הביצועים של התמונות שהוספנו ל-Angular היו חלק מההוראה NgOptimizedImage. אם לא משתמשים בהנחיה באפליקציה, לא תקבלו הנחיות לגבי בעיות בביצועים של תמונות.

ב-Agular 17 אנחנו מרחיבים את היקף ההנחיות לביצועי תמונות, כך שהן יכללו את כל האפליקציות של Angular. עכשיו, אם נזהה דפוסי תמונות שאנחנו יודעים שהם שגיאות שמשפיעות לרעה על הביצועים, כמו טעינת פריטים בזמן אמת (lazy-loading) של התמונה של LCP או הורדה של קובץ גדול מדי לדף, נודיע לכם על כך, גם אם אתם לא משתמשים ב-NgOptimizedImage.

ביצועי התמונות חשובים לכל האפליקציות, ואנחנו שמחים להמשיך לפתח אמצעי הגנה שיעזרו למנוע טעויות נפוצות באפליקציות Angular.

ומה בעתיד?

אנחנו כבר עובדים במרץ על פיתוח הקבוצה הבאה של התכונות ל-NgOptimizedImage. ביצועי התמונות עדיין נמצאים בראש סדר העדיפויות שלנו, אבל אנחנו רוצים גם להוסיף תכונות שמשפרות את חוויית הפיתוח, כדי לוודא ש-NgOptimizedImage תישאר אפשרות אטרקטיבית להכללת תמונות באפליקציות Angular.

אחד מהפיצ'רים שחשובים לנו במיוחד הוא placeholders של תמונות. בדרך כלל משתמשים בהן כדי לשפר את הטעינה של תמונות באפליקציות אינטרנט, אבל אם מטמיעים אותן בצורה שגויה, הן עלולות לפגוע בביצועים. אנחנו מקווים לפתח ב-NgOptimizedImage מערכת placeholder של תמונות שמתמקדת בביצועים. כדאי לעקוב אחרי העדכונים בבלוג שלנו.