ביצועי תמונה

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

אפשר להוסיף תמונות לדף באמצעות האלמנטים <img> או <picture>, או באמצעות המאפיין background-image ב-CSS.

Image size

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

עם זאת, יש הרבה משתנים שקשורים לבחירת גודל התמונה המתאים, ולכן המשימה של בחירת גודל התמונה המתאים בכל מקרה היא מורכבת למדי. בשנת 2010, כשה-iPhone 4 יצא לשוק, רזולוציית המסך (640x960) הייתה כפולה מזו של ה-iPhone 3 (320x480). עם זאת, הגודל הפיזי של המסך של iPhone 4 נשאר בערך זהה לזה של iPhone 3.

הצגת כל התמונות והטקסט ברזולוציה גבוהה יותר הייתה מקטינה אותם באופן משמעותי – במדויק, לחצי מהגודל הקודם שלהם. במקום זאת, פיקסל אחד הפך לשני פיקסלים במכשיר. היחס הזה נקרא יחס הפיקסלים של המכשיר (DPR). לדגם iPhone 4 – ולדגמי iPhone רבים שיצאו אחריו – היה DPR של 2.

נחזור לדוגמה הקודמת: אם למכשיר יש DPR של 2 והתמונה מוצגת במאגר בגודל 500 על 500 פיקסלים, אז התמונה האופטימלית היא תמונה ריבועית בגודל 1, 000 פיקסלים (שנקראת גודל מהותי). באופן דומה, אם להתקן יש DPR של 3, הגודל האופטימלי הוא תמונה ריבועית בגודל 1,500 פיקסלים.

srcset

הרכיב <img> תומך במאפיין srcset, שמאפשר לציין רשימה של מקורות תמונות אפשריים שהדפדפן עשוי להשתמש בהם. כל מקור תמונות שצוין חייב לכלול את כתובת ה-URL של התמונה, וכן תיאור של רוחב או של צפיפות הפיקסלים.

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

קטע ה-HTML הקודם משתמש בתיאור של צפיפות הפיקסלים כדי להציע לדפדפן להשתמש ב-image-500.png במכשירים עם DPR של 1, ב-image-1000.jpg במכשירים עם DPR של 2 וב-image-1500.jpg במכשירים עם DPR של 3.

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

sizes

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

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

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

בקטע הקוד הקודם של ה-HTML, המאפיין srcset מציין רשימה של תמונות מועמדות שהדפדפן יכול לבחור מתוכן, מופרדות בפסיקים. כל מועמדת ברשימה מורכבת מכתובת ה-URL של התמונה, ואחריה תחביר שמציין את רוחב התמונה המובנה. הגודל המובנה של תמונה הוא המידות שלה. לדוגמה, מתאר של 1000w מציין שהרוחב הפנימי של התמונה הוא 1,000 פיקסלים.

על סמך המידע הזה, הדפדפן מעריך את תנאי המדיה במאפיין sizes, ובמקרה הזה מקבל הוראה שאם רוחב שדה התצוגה של המכשיר עולה על 768 פיקסלים, התמונה תוצג ברוחב של 500 פיקסלים. במכשירים קטנים יותר, התמונה תוצג בגודל 100vw – או ברוחב מלא של אזור התצוגה.

לאחר מכן, הדפדפן יכול לשלב את המידע הזה עם רשימת מקורות התמונות srcset כדי למצוא את התמונה האופטימלית. לדוגמה, אם המשתמש משתמש במכשיר נייד עם רוחב מסך של 320 פיקסלים ושיעור דחיסה נתון של 3, התמונה תוצג ב-320 CSS pixels x 3 DPR = 960 device pixels. בדוגמה הזו, התמונה הקרובה ביותר בגודל היא image-1000.jpg, שרוחב המקור שלה הוא 1,000 פיקסלים (1000w).

פורמטים של קבצים

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

WebP הוא פורמט שנתמך באופן נרחב ופועל בכל הדפדפנים המודרניים. לרוב, דחיסת הנתונים ב-WebP טובה יותר מאשר ב-JPEG, ב-PNG או ב-GIF, והיא כוללת גם דחיסת נתונים עם אובדן נתונים וגם דחיסת נתונים ללא אובדן נתונים. ב-WebP יש גם תמיכה בשקיפות של ערוץ אלפא גם כשמשתמשים בדחיסת נתונים מסוג lossy – תכונה שלא קיימת בקודק של JPEG.

AVIF הוא פורמט תמונה חדש יותר, וגם אם הוא לא נתמך באופן נרחב כמו WebP, יש לו תמיכה סבירה בדפדפנים. פורמט AVIF תומך גם ברזולוציה עם אובדן נתונים וגם ברזולוציה ללא אובדן נתונים, ובבדיקות נמצאו במקרים מסוימים חיסכון של יותר מ-50% בהשוואה ל-JPEG. ב-AVIF יש גם תכונות של Wide Color Gamut‏ (WCG) ושל High Dynamic Range‏ (HDR).

דחיסה

לגבי תמונות, יש שני סוגים של דחיסה:

  1. דחיסת נתונים עם אובדן נתונים
  2. דחיסת נתונים ללא אובדן נתונים

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

דחיסת נתונים ללא אובדן נתונים מקטינה את גודל הקובץ על ידי דחיסת תמונה ללא אובדן נתונים. בדחיסה ללא אובדן נתונים, הפיקסל מתואר על סמך ההבדל בינו לבין הפיקסלים הסמוכים. דחיסת lossless משמשת בפורמטים של תמונות GIF,‏ PNG,‏ WebP ו-AVIF.

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

הרכיב <picture>

הרכיב <picture> מאפשר לכם לציין מספר תמונות מועמדות בצורה גמישה יותר:

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

כשמשתמשים באלמנטים <source> בתוך האלמנט <picture>, אפשר להוסיף תמיכה בתמונות AVIF ו-WebP, אבל לעבור לפורמטים ישנים יותר של תמונות אם הדפדפן לא תומך בפורמטים מודרניים. בגישה הזו, הדפדפן בוחר את אלמנט <source> הראשון שצוין שמתאים. אם המערכת יכולה להציג את התמונה בפורמט הזה, היא משתמשת בתמונה הזו. אחרת, הדפדפן עובר לרכיב <source> הבא שצוין. בקטע הקוד הקודם של ה-HTML, לפורמט AVIF יש עדיפות על פני פורמט WebP, והוא יעבור לפורמט JPEG אם לא תהיה תמיכה ב-AVIF או ב-WebP.

אלמנט <picture> מחייב אלמנט <img> שמוטמע בתוכו. המאפיינים alt, ‏ width ו-height מוגדרים ב-<img>, והם משמשים ללא קשר ל-<source> שנבחר.

הרכיב <source> תומך גם במאפיינים media, srcset ו-sizes. בדומה לדוגמה של <img> שלמעלה, הפרמטרים האלה מציינים לדפדפן איזו תמונה לבחור בחלונות תצוגה שונים.

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

המאפיין media מקבל תנאי מדיה. בדוגמה הקודמת, רזולוציית המסך של המכשיר משמשת כתנאי המדיה. כל מכשיר עם DPR שגדול מ-1.5 או שווה לו ישתמש ברכיב <source> הראשון. האלמנט <source> מורה לדפדפן שבמכשירים עם אזור תצוגה ברוחב של יותר מ-768 פיקסלים, התמונה שנבחרה תוצג ברוחב 500 פיקסלים. במכשירים קטנים יותר, הרכיב הזה תופס את כל רוחב אזור התצוגה. שילוב המאפיינים media ו-srcset מאפשר לכם לשלוט בצורה מדויקת יותר בתמונה שבה תרצו להשתמש.

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

רוחב אזור התצוגה (פיקסלים) 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

במכשירים עם DPR של 1 מתבצעת הורדה של התמונה image-500.jpg, כולל אצל רוב המשתמשים במחשב – שהתמונה מוצגת אצלם בגודל חיצוני של 500 פיקסלים רוחב. לעומת זאת, משתמשים בנייד עם DPR של 3 מורידים image-1500.jpg גדול יותר, שזהה לתמונה שמשמשת במחשבים עם DPR של 3.

<picture>
  <source
    media="(min-width: 561px) 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>

בדוגמה הזו, האלמנט <picture> מותאם כך שיכלול אלמנט <source> נוסף כדי להשתמש בתמונות שונות במכשירים רחבים עם DPR גבוה:

רוחב אזור התצוגה (פיקסלים) 1 DPR 1.5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 1000-sm.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

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

לחלופין, אפשר לשנות את המאפיינים srcset ו-media כדי למנוע הצגת תמונות גדולות בחלונות צפייה קטנים:

<picture>
  <source
    media="(min-width: 561px)"
    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>

בקטע הקוד הקודם ב-HTML, מתארי הרוחב הוסרו לטובת מתארי יחס הפיקסלים של המכשיר. התמונות שמוצגות במכשיר נייד מוגבלות ל-/image-500.jpg או ל-/image-1000.jpg, גם במכשירים עם רזולוציית צפייה של 3.

איך מנהלים את המורכבות

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

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

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

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

הצגת תמונות על סמך הכותרת Accept בבקשה

כותרת הבקשה של ה-HTTP‏ Accept מעדכנת את השרת אילו סוגי תוכן הדפדפן של המשתמש מבין. השרת יכול להשתמש במידע הזה כדי להציג את פורמט התמונה האופטימלי בלי להוסיף עוד בייטים לתשובות ה-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');

קטע ה-HTML הקודם הוא גרסה פשוטה של הקוד שאפשר להוסיף לקצה העורפי של JavaScript בשרת כדי לבחור את פורמט התמונה האופטימלי ולהציג אותו. אם כותרת הבקשה Accept כוללת את image/avif, תמונה בפורמט AVIF תוצג. אחרת, אם הכותרת Accept כוללת את image/webp, תוצג תמונה בפורמט WebP. אם אף אחד מהתנאים האלה לא מתקיים, תוצג תמונה בפורמט JPEG.

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

ההתנהגות הזו דומה לזו של רשת להעברת תוכן (CDN) של תמונות. רשתות CDN לתמונות הן פתרונות מצוינים לאופטימיזציה של תמונות ולשליחת הפורמט האופטימלי בהתאם למכשיר ולדפדפן של המשתמש.

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

טעינה מדורגת

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

decoding

המאפיין decoding מציין לדפדפן איך לפענח את התמונה. הערך async מורה לדפדפן שאפשר לפענח את התמונה באופן אסינכרוני, וכך אולי לקצר את זמן העיבוד של תוכן אחר. הערך sync מורה לדפדפן שהתמונה צריכה להופיע בו-זמנית עם תוכן אחר. ערך ברירת המחדל של auto מאפשר לדפדפן להחליט מה הכי מתאים למשתמש.

הדגמות של תמונות

בוחנים את הידע

באילו פורמטים של תמונות יש תמיכה בדחיסת lossless?

GIF.
תשובה נכונה!
JPEG.
אפשר לנסות שוב.
PNG.
תשובה נכונה!
WebP.
תשובה נכונה!
AVIF.
תשובה נכונה!

באילו פורמטים של תמונות יש תמיכה בדחיסת lossy?

GIF.
אפשר לנסות שוב. פורמט ה-GIF תומך רק בצבעים מוגבלים של 256 צבעים, אבל צריך לבצע קידוד עם אובדן נתונים לפני ההמרה ל-GIF.
JPEG.
תשובה נכונה!
PNG.
אפשר לנסות שוב.
WebP.
תשובה נכונה!
AVIF.
תשובה נכונה!

מה מתאר הרוחב (לדוגמה, 1000w) מספר לדפדפן לגבי מועמד לתמונה שצוין במאפיין srcset?

רוחב חיצוני של התמונה – כלומר, המידות של התמונה בפריסה אחרי שהסגנונות הוחלו על הדף
אפשר לנסות שוב.
הרוחב הפנימי של התמונה – כלומר, המידות של התמונה עצמה.
תשובה נכונה!

מה המאפיין sizes אומר לדפדפן לגבי רכיב <img> שאליו הוא מיושם?

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

בקטע הבא: ביצועי הסרטון

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