אופטימיזציה של תמונות באמצעות ההנחיה בנושא תמונות זוויתיות

קארה אריקסון
קארה אריקסון
לינה סוהוני
לינה סוהוני

במאי 2022 הצוותים של Aurora ו-Agular הכריזו שהם ישתפו פעולה לגבי הוראת תמונות עבור Angular. ההנחיה פורסמה לאחרונה לתצוגה מקדימה למפתחים כחלק מ-Angular v14.2. בפוסט הזה נסביר איך הוראת התמונה החדשה, NgOptimizedImage, תומכת באופטימיזציה של תמונות ב-Angular.

רקע

תמונות הן רכיב נפוץ וקריטי בחוויית המשתמש באינטרנט, כאשר 99.9% מדפי האינטרנט מייצרים בקשות לתמונה אחת או יותר. תמונות הן גם הגורמים המשמעותיים ביותר למשקל הדף, והם מהווים חציון של 982 קילובייט לדף.

בגלל המספר והגודל של תמונות, הן יכולות לפגוע בביצועים של דפי אינטרנט ולהשפיע על מדדים של מדדי הליבה לבדיקת חוויית המשתמש באתר. ב-2021, ב-79.4% מהדפים במחשב, תמונה נכללה ברכיב Largest Contentful Paint (LCP). כיום, רבים מאיתנו צריכים להשקיע הרבה מאוד בתמונות כדי לשפר את איכות התמונה.

צוות Aurora מאמין למנף את העוצמה של frameworks כדי לספק פתרונות כוללים לאתגרים נפוצים של מפתחים. הכניסה הראשונה שלהם למרחב האופטימיזציה של התמונות הייתה רכיב התמונה Next.js. הם חשבו שהרכיב הזה הוא סביבה לבדיקת האם שיפור חוויית המפתח (DX) באופטימיזציה של תמונות יכול להוביל לשיפור הביצועים של יותר אפליקציות שמשתמשות ב-frameworks.

קבוצת התוצאות הראשונה של משתמש Next.js Leboncoin הייתה עודדה. קבוצת Leboncoin נהנתה משיפור משמעותי ב-LCP (מ-2.4 שניות ל-1.7 שניות) אחרי שהתחילו להשתמש ב-next/image. לשימוש מאוחר יותר של next/image בקהילה הייתה השפעה על העלייה שמקורות Next.js שעמדו בדרישות הסף של LCP. בקרוב נשלחו בקשות לתכונות דומות במסגרות אחרות, שאחת מהן הייתה Angular.

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

Opportunity

Angular היא אחת ממסגרות ה-JavaScript המובילות שבהן משתמשים מפתחים כיום. הוא נמצא בשימוש ביותר מ-50,000 מקורות שנסרקו על ידי HTTPArchive בנייד, ויש בו כמעט 3 מיליון הורדות שבועיות ב-NPM.

LCP באתרים של Angular בשנה האחרונה.

כשבוחנים את הציונים במדדי הליבה לבדיקת חוויית המשתמש באתר, אפשר עדיין לבדוק מהו אחוז המקורות ה-Agular שעומדים בספי LCP 'טובים'. רק ב-18.74% מהאתרים ב-Agular היו נתוני LCP טובים בניידים ביוני 2022. תמונות הן רכיב ה-LCP ביותר מ-70% מדפי האינטרנט בניידים ובמחשבים, ולכן תמונות LCP לא אופטימליות עשויות להיות אחד מהגורמים העיקריים לירידה ברמת LCP באתרים ב-Angular.

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

MVP בהוראה NgOptimizedImage

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

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

אלה המאפיינים הבולטים של העיצוב:

  1. טעינה מדורגת חכמה

    באופן אידיאלי, רצוי להטען באופן מדורג תמונות שאינן גלויות למשתמש בזמן טעינת הדף (לדוגמה, תמונות בחלק הנגלל או תמונות קרוסלה מוסתרות). טעינה עצלה מתפנה משאבים בדפדפן לטעינה של טקסט, מדיה או סקריפטים קריטיים אחרים. רוב התמונות לא קריטיות וצריך לטעון אותן בהדרגה, אבל רק ב-7.8% מהדפים נעשה שימוש בטעינה מדורגת מובנית בשנת 2021.

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

  2. תעדוף של תמונות קריטיות

    הוספת רמזים למשאבים (למשל preload או preconnect) כדי לתת עדיפות לטעינה של תמונות קריטיות היא השיטה המומלצת. עם זאת, רוב האפליקציות לא משתמשות בהן. לפי אלמנאק האינטרנט לשנת 2021, רק 12.7% מהדפים לנייד משתמשים ברמזים לקישור מראש, ורק ב-22.1% מהדפים לנייד משתמשים ברמזים לטעינה מראש.

    הוראת התמונה פועלת בשתי חזיתות כאשר תמונות מסומנות כחשובות.

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

    במצב פיתוח, ההוראה משתמשת גם ב-PerformanceObserver API כדי לוודא שתמונת ה-LCP סומנה כמצופה priority. אם הוא לא מסומן כ-priority, תוצג שגיאה שתנחה את המפתח להוסיף את המאפיין priority לתמונת ה-LCP.

    בסופו של דבר, השילוב הזה של אוטומציה ותאימות מבטיח שלתמונה מסוג LCP יהיה רמז preconnect וערך המאפיין fetchpriority הוא high, ושלא תתבצע טעינה מדורגת.

  3. תצורה אופטימלית לשימוש בכלי תמונות פופולריים

    מומלץ לאפליקציות ב-Agular להשתמש ב-Image CDNs, שמספקים בדרך כלל שירותי אופטימיזציה כברירת מחדל.

    ההנחיה מעודדת שימוש ברשתות CDN עם תמונות על ידי הצעת חוויית מפתח מושכת במיוחד (DX) כדי להגדיר אותם באפליקציה. היא תומכת בממשק API של טעינה שמאפשר לך להגדיר את ספק ה-CDN ואת כתובת האתר הבסיסית בתצורה שלך. אחרי שמגדירים את הנכס, צריך רק להגדיר את שם הנכס בתגי העיצוב. לדוגמה,

    // in module providers:
    provideImgixLoader('https://mysite.net/assets/')
    
    // in markup
    <img ngSrc="image.png" >
    <img ngSrc="image2.png" >
    

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

    <img src="https://mysite.net/assets/image.png">
    <img src="https://mysite.net/assets/image2.png">
    

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

  4. שגיאות ואזהרות מובנות

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

    1. תמונות לא בגודל: ההנחיה של התמונה גורמת לשגיאה אם לתגי העיצוב של התמונה לא הוגדרו רוחב וגובה מפורשים. תמונות לא בגודל עלול לגרום לתנודות בפריסה, שישפיעו על המדד Cumulative Layout Shift (CLS) של הדף. כדי למנוע מצב כזה, מומלץ לציין בתמונות את המאפיינים width ו-height.

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

      1. הגדרת בטעות מימדים (רוחב או גובה) שגויים, או
      2. אם הגדרתם מאפיין אחד לאחוז ב-CSS אבל לא את השני (לדוגמה, width: 100% צריך height: auto כדי להבטיח שהתמונה תגדל בשני המימדים).
    3. תמונות גדולות מדי: אם אין בתמונה הגדרה של srcset והתמונה הפנימית גדולה באופן משמעותי מהתמונה המעובדת, בהוראה תופיע אזהרה שמציעה שימוש במאפיינים srcset ו-sizes.

    4. דחיסות תמונות: אם תנסו לכלול תמונה ב-srcset עם צפיפות פיקסלים של יותר מ-3x, תופיע הודעת שגיאה. בדרך כלל לא מומלץ להשתמש במתארים שגבוהים מ-2x כי יש לכך תוצאה בלתי מכוונת של אילוץ הורדה של תמונות ענקיות על מכשירים ניידים ברזולוציה גבוהה. בנוסף, העין האנושית לא יכולה לזהות הבדל גדול מפי 2.

אתגרים

כשעיצבנו את NgOptimizedImage, השימוש באסטרטגיות לאופטימיזציה של תמונות כך שיעבוד במסגרת בצד הלקוח היה האתגר העיקרי. חוויית הרינדור שמוגדרת כברירת מחדל ב-Next.js היא עיבוד בצד השרת (SSR) או יצירת אתרים סטטיים (SSG), ואילו ב-Angular זהו עיבוד בצד הלקוח (CSR). למרות ש-Angular תומך בספריית SSR – זוויתית/אוניברסלית – רוב האפליקציות ב-Angular (כ-60%) משתמשות בנציג שירות לקוחות.

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

אלה כמה מהאתגרים שבהם אנחנו נתקלים:

  1. תמיכה ברמזים לגבי משאבים

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

    הוספה ידנית: למפתחים קשה להוסיף את רמז המשאב preload באופן ידני. Angular משתמש בקובץ index.html משותף אחד לכל הפרויקט או לכל הנתיבים באתר. לכן, <head> של המסמך זהה בכל מסלול (לפחות בזמן ההגשה). אם מוסיפים רמז של preload ל-<head>, המשאב ייטען מראש לכל המסלולים גם כשאין בו צורך. לכן, לא מומלץ להוסיף ידנית רמזים מסוג preload.

    הוספה אוטומטית במהלך העיבוד: שימוש ב-framework כדי להוסיף רמזים לטעינה מראש לראש המסמך במהלך העיבוד באפליקציית CSR לא מועיל. מאחר שהעיבוד מתרחש לאחר ההורדה וההפעלה של JavaScript, העיבוד של <head> יהיה מאוחר מדי ולא יהיה בעל ערך.

    בגרסה הראשונה של ההנחיה, שילוב של רמזים מסוג preconnect ורמזים מסוג fetchpriority משמש כדי לתעדף את התמונה במקום preload. עם זאת, Aurora עובדת כרגע עם צוות Angular CLI כדי לאפשר הזרקה אוטומטית של רמזים למשאבים בזמן ה-build - כדאי להמשיך להתעדכן!

  2. אופטימיזציה של הגודל והפורמט של התמונה בשרת

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

    אמנם ההנחיה לא אוכפת את השימוש ב-CDN של תמונות, אבל מומלץ מאוד להשתמש בהם יחד עם ההוראה והמטענים המובנים שלה מבטיחים שנעשה שימוש באפשרויות ההגדרה הנכונות.

השפעה

ההדגמה הבאה ממחישה את ההבדל שהוראת Angular image יכולה לבצע לביצועי התמונה. הוא משווה בין שני אתרים:

אתר One: משתמש ברכיבים מקוריים של <img> עם תמונות שמוצגות דרך Imgix CDN (עם אפשרויות הגדרה שמוגדרות כברירת מחדל).

אתר 2: משתמשים בהוראת התמונה לכל התמונות. היא כוללת גם אופטימיזציות שמומלצות באופן ישיר על ידי אזהרות או שגיאות שנגרמו על ידי ההוראה.

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

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

אחד מהשותפים האלה היה Land's End. היה צפוי שהאתר שלהם יהיה דוגמה טובה לבדיקת תוצאות שיישומים אמיתיים עשויים לראות.

בוצעו בדיקות Lab של Lighthouse בסביבת בקרת האיכות לפני ואחרי השימוש בהוראת התמונה. במחשב, שיעור ה-LCP החציוני שלהם ירד מ-12.0 שניות ל-3.0 שניות, שיפור של 75% ב-LCP. בניידים, מדד ה-LCP החציוני ירד מ-20.2 שניות ל-12.0 שניות (שיפור של 40.6%).

מפת דרכים עתידית

זה רק החלק הראשון בעיצוב של ה-Agular image Directive (הדירקטיבה לתמונות זוויתיות). בגרסאות עתידיות יש הרבה תכונות נוספות, כולל:

  • תמיכה משופרת בתמונות רספונסיביות:

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

  • הזרקה אוטומטית של רמזים למשאבים

    יכול להיות שאפשר יהיה לשלב את ה-Angular CLI כדי ליצור תגים לקישור מראש ולטעינה מראש עבור תמונות LCP קריטיות.

  • תמיכה ב-Agular SSR

    גרסת ה-MVP מתוכננת תוך התחשבות במגבלות של Angular CSR, אך חשוב גם לבדוק פתרונות לאופטימיזציה של תמונות עבור Angular SSR (זוויתי/אוניברסלי).

  • שיפורים בחוויית המפתחים

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

    1. לתמוך במצב נוסף (בדומה לאפשרות פריסת התמונה ב-Next.js "fill") שלא מצריך הגדרה של רוחב/גובה מפורש.
    2. שימוש בשילוב עם CLI כדי להגדיר באופן אוטומטי את הרוחב והגובה של תמונות מקומיות על ידי קביעת המידות בפועל של התמונה.

סיכום

ההנחיה של תמונות Angular תהיה זמינה למפתחים בשלבים, החל מגרסת התצוגה המקדימה למפתחים בגרסה 14.2.0. אנחנו מזמינים אותך לנסות את NgOptimizedImage ולשלוח משוב!

תודה מיוחדת לקייטי המפניוס ולאלכס קאסל על התרומה שלהם.