ביצועי תמונה

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

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

Image size

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

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

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

נחזור לדוגמה הקודמת. אם למכשיר יש ערך DPR של 2 והתמונה מוצגת במאגר של 500 פיקסלים על 500 פיקסלים, עכשיו הגודל האופטימלי הוא תמונה ריבועית של 1, 000 פיקסלים (שנקראת גודל פנימי). באופן דומה, אם למכשיר יש 3DPR, אז תמונה ריבועית של 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.

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

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 פיקסלים עם DPR של 3, התמונה תוצג ב-320 CSS pixels x 3 DPR = 960 device pixels. בדוגמה הזו, התמונה בגודל הקרוב ביותר תהיה image-1000.jpg, ברוחב פנימי של 1,000 פיקסלים (1000w).

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

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

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

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

דחיסה

כשמדובר בתמונות, יש שני סוגי דחיסה:

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

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

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

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

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

רוחב אזור התצוגה (בפיקסלים) DPR אחד 1.5 DPR 2 DPR 3 DPR
320 500.jpg 500.jpg 500.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: 560px)"
    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, גם במכשירים עם DPR של 3.

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

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

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

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

מלבד זאת, הגודל של מסמך ה-HTML שלך גדל עם כל גרסה. אתם עשויים לשלוח כמה קילובייט (KB) של 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 של תמונות הן פתרונות מצוינים לאופטימיזציה של תמונות ולשליחת הפורמט האופטימלי בהתאם למכשיר ולדפדפן של המשתמש.

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

טעינה מדורגת

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

decoding

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

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

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

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

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

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

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

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

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

מה מאפיין sizes מציין לדפדפן על רכיב <img> שעליו הוא חל?

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

השלב הבא: ביצועי סרטונים

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