יצירת מקורות של תמונות שמניבים ביצועים טובים היא חלק חלק מ או בלתי מונחית.
כל התחביר בקורס הזה – מקידוד נתוני תמונה ועד צפיפות המידע
תגי עיצוב שמפעילים תמונות רספונסיביות – אלה שיטות לתקשורת עם מכונות. יש לך
גילה כמה דרכים שבהן דפדפן לקוח יכול להעביר את צורכיו לשרת ולשרת תגובה באופן דומה.
תגי עיצוב של תמונות רספונסיביות (srcset
ו-sizes
, במיוחד) מאפשרים לתאר כמות מזעזעת של מידע באופן יחסי
כמה תווים. לטוב ולרע, הסיכום הזה נקבע בתכנון: הוא הופך את התחביר של התחביר לפחות לקצר יותר, כך למפתחים שיהיה קל יותר למצוא אותו.
עשויים להקשות על ניתוח הנתונים בדפדפן. ככל שמוסיפים יותר מורכבות למחרוזת, כך
פוטנציאל לשגיאות מנתח או להבדלים לא מכוונים בהתנהגות בין דפדפן אחד לדפדפן.
עם זאת, אותה תכונה שעלולה לגרום לנושאים האלה להרגיש כל כך מפחידים יכולה לספק לכם גם פתרונות: תחביר בקלות קריאה על ידי מכונות היא תחביר שנכתב יותר על ידי מכונות. נתקלת בסבירות גבוהה בהרבה דוגמאות של קידוד ודחיסה של תמונות כמשתמש באינטרנט: כל תמונה שהועלתה לאינטרנט דרך פלטפורמות של רשתות חברתיות, תוכן מערכות ניהול (CMS), ואפילו לקוחות אימייל יעברו דרך כמעט בלתי הפיכה דרך מערכת שמשנה את הגודל, מקודדת מחדש, ולדחוס אותם.
באופן דומה, בין אם באמצעות יישומי פלאגין, ספריות חיצוניות, כלים עצמאיים לתהליך build או שימוש אחראי בסקריפטים בצד הלקוח, תגי עיצוב של תמונות רספונסיביות מתאימים בקלות לאוטומציה.
אלה שני החששות העיקריים לגבי אוטומציה של ביצועי תמונות: ניהול יצירת התמונות – הקידודים שלהן,
דחיסת נתונים, והמקורות החלופיים שבהם משתמשים כדי לאכלס מאפיין srcset
— וליצור תגי עיצוב גלויים למשתמשים.
ביחידה הזו נלמד כמה גישות נפוצות לניהול תמונות כחלק מתהליך עבודה מודרני,
שלב אוטומטי בתהליך הפיתוח, באמצעות המסגרת או מערכת ניהול התוכן שמפעילים את האתר, או
מופשט כמעט לחלוטין על ידי רשת ייעודית להעברת תוכן.
אוטומציה של דחיסה וקידוד
סביר להניח שלא תגיעו למצב שבו תוכלו להקדיש זמן כדי לקבוע באופן ידני את הקידוד והרמה האידיאליים. דחיסה של כל תמונה שמיועדת לשימוש בפרויקט, וגם לא היית רוצה. בתור חשוב מאוד לשמור על גודל קטן ככל האפשר של העברת התמונות, יצירת הגדרות דחיסה ושמירה מחדש של מקורות חלופיים לכל נכס תמונות שמיועד לאתר ייצור הכנסות צוואר בקבוק ענק בעבודה היומיומית.
כפי שלמדתם כשקראתם את הפורמטים השונים של תמונות ואת סוגי הדחיסה, הקידוד היעיל ביותר של תמונה תמיד ייקבע על ידי של התוכן, וכמו שלמדתם בתמונות רספונסיביות, הגדלים החלופיים שדרושים למקורות התמונות יהיו נקבע על ידי המיקום של התמונות האלה בפריסת הדף. בתהליך עבודה מודרני הגישה להחלטות האלה באופן הוליסט, במקום בנפרד – קביעת קבוצה של ברירות מחדל הגיוניות עבור תמונות, כך שיתאימו בצורה הטובה ביותר בהקשרים שבהם שהם נועדו להשתמש בהם.
כשבוחרים קידודים לספרייה של תמונות מצולמות, הפורמט AVIF הוא המנצח הברור מבחינת האיכות וגודל ההעברה אבל יש לו תמיכה מוגבלת, WebP מספק חלופה מודרנית ומשופרת, וברירת המחדל האמינה ביותר היא JPEG. החלופה הגדלים שאנחנו צריכים להפיק לתמונות שמיועדות לתפוס סרגל צד בפריסת דף יהיו שונים מאוד מאלה של תמונות שאמורות להיות כך שיתפוס את כל אזור התצוגה של הדפדפן בנקודות העצירה (breakpoint) הגבוהות ביותר שלנו. הגדרות דחיסה יחייבו תשומת לב כדי לטשטש ארטיפקטים מדחיסת נתונים וקובץ דחיסה מרובים של קבצים שנוצרו כתוצאה מכך - כך שיש פחות מקום לחתוך כל בייט אפשרי מכל תמונה בתמורה לתהליך עבודה גמיש ואמין יותר. לסיכום, תצטרכו לפעול לפי אותו תהליך קבלת החלטות שאתם להבין מהקורס הזה, בגדול.
לגבי העיבוד עצמו, יש מספר עצום של ספריות קוד פתוח לעיבוד תמונות שמספקות שיטות המרה, שינוי ועריכה של תמונות בכמות גדולה, המתחרים על המהירות, היעילות והאמינות. העיבודים האלה יאפשרו להחיל הגדרות קידוד ודחיסה על ספריות שלמות של תמונות בו-זמנית, ללא לפתוח את התוכנה לעריכת תמונות, ובצורה ששומרת את מקורות התמונה המקוריים שאפשר להתאים אותם תוך כדי תנועה. הם מיועדים להפעלה בהקשרים שונים, מסביבת הפיתוח המקומית ועד שרת האינטרנט עצמו - לדוגמה, ה-ImageMin שמתמקדת בדחיסה אפשר להרחיב את Node.js לאפליקציות ספציפיות באמצעות מגוון של יישומי פלאגין, ואילו ImageMagick בפלטפורמות שונות ו-Sharp שמבוסס על Node.js מגיעים עם מספר מפתיע של תכונות, שיצאו מהאריזה.
ספריות עיבוד התמונות האלו מאפשרות למפתחים ליצור כלים שמיועדים לאופטימיזציה חלקה של תמונות כחלק מתהליכי הפיתוח הרגילים שלכם — כך שהפרויקט שלכם תמיד יתייחס לקובץ התמונה שמוכן לייצור מקורות עם תקורה נמוכה ככל האפשר.
כלים ותהליכי פיתוח מקומיים
אפשר להשתמש במריצים במשימות ובחבילות כמו Graunt, Gulp או Webpack כדי: לבצע אופטימיזציה של נכסי תמונות לצד משימות נפוצות אחרות שקשורות לביצועים, כמו הקטנה של CSS ו-JavaScript. שפת תרגום בואו ניקח תרחיש לדוגמה פשוט יחסית: ספרייה בפרויקט שלכם מכילה תריסר תמונות מצולמות, שמיועד לשימוש באתר ציבורי.
קודם כל, תצטרכו לוודא שהקידוד של התמונות האלה עקבי ויעיל. כפי שלמדתם במודולים הקודמים,
WebP הוא ברירת מחדל יעילה לתמונות מצולמות, גם מבחינת האיכות וגם של גודל הקובץ. ה-WebP נתמך גם,
אבל לא נתמכת באופן אוניברסלי, לכן כדאי גם לכלול חלופה בפורמט JPEG. לאחר מכן:
כדי להשתמש במאפיין srcset
להצגה יעילה של הנכסים האלה, צריך ליצור כמה
גדלים חלופיים לכל קידוד.
אבל אם תעשו זאת בעזרת תוכנה לעריכת תמונות, אלו משימות שחוזרות על עצמן וימשכו הרבה זמן.
Gulp נועדו להפוך פעולות חוזרות מהסוג הזה לאוטומטיות. המודעה רספונסיבית
באמצעות Sharp, הפלאגין הוא רק אפשרות אחת מתוך רבות שמופיעות בדפוס דומה:
לאסוף את כל הקבצים בספריית מקור, לקודד אותם מחדש ולדחוס אותם לפי אותה 'איכות' סטנדרטית
קיצור דרך שלמדתם במאמר פורמטים של תמונות ודחיסה. הקבצים שיופקו הם פלט לנתיב שתגדירו,
מוכנים להפניה במאפייני src
של רכיבי img
שגלויים למשתמשים, אבל הקבצים המקוריים יישארו ללא שינוי.
const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');
exports.webp = function() {
return src('./src-img/*')
.pipe(respimg({
'*': [{
quality: 70,
format: ['webp', 'jpeg'],
progressive: true
}]
}))
.pipe(dest('./img/'));
}
כשהתהליך מתבצע, לא יפגע בסביבת הייצור אם מישהו עובד בפרויקט בטעות הוסיפו תמונה שמקודדת בפורמט PNG גדול מסוג truecolor לספרייה שמכילה את מקורות התמונות המקוריים – בלי קשר בקידוד של התמונה המקורית, המשימה הזו תיצור WebP יעיל, חלופה אמינה ל-Progressive JPEG, רמת דחיסה שניתנת להתאמה בקלות תוך כדי תנועה. כמובן, תהליך זה מבטיח גם שהתמונה המקורית יישמרו בסביבת הפיתוח של הפרויקט, כלומר ניתן לשנות את ההגדרות האלה בכל רק כשהפלט האוטומטי יוחלף.
כדי ליצור פלט של מספר קבצים, יש להעביר מספר אובייקטים של תצורה — כולם באותו אופן, מלבד ההוספה של
מפתח width
וערך בפיקסלים:
const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');
exports.default = function() {
return src('./src-img/*')
.pipe(respimg({
'*': [{
width: 1000,
format: ['jpeg', 'webp'],
progressive: true,
rename: { suffix: '-1000' }
},
{
width: 800,
format: ['jpeg', 'webp'],
progressive: true,
rename: { suffix: '-800' }
},
{
width: 400,
format: ['jpeg', 'webp'],
progressive: true,
rename: { suffix: '-400' },
}]
})
)
.pipe(dest('./img/'));
}
במקרה לדוגמה שלמעלה, התמונה המקורית (monarch.png) הייתה גדולה מ-3.3MB. הקובץ הגדול ביותר שנוצר על ידי גודל המשימה (monarch-1000.jpeg) הוא בערך 150KB. הקטן ביותר, monarch-400.web, הוא רק 32KB.
[10:30:54] Starting 'default'...
[10:30:54] gulp-responsive: monarch.png -> monarch-400.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-800.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-400.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-800.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.webp
[10:30:54] gulp-responsive: Created 6 images (matched 1 of 1 image)
[10:30:54] Finished 'default' after 374 ms
כמובן, כדאי לבחון בקפידה את התוצאות של ארטיפקטים גלויים של דחיסה, או אולי להגדיל את הדחיסה לחיסכון נוסף. מאחר שהמשימה אינה הרסנית, ניתן לשנות את ההגדרות האלה בקלות.
בתמורה לכמה הקילובייט (KB) שאפשר להפחית בעזרת מיקרו-אופטימיזציה ידנית קפדנית, אתם מקבלים תהליך שאינו רק יעיל, אלא עמיד – כלי שמיישם בצורה חלקה את הידע שלכם על נכסי תמונות שמניבים ביצועים טובים. לפרויקט כולו, ללא התערבות ידנית.
שימוש בתגי עיצוב של תמונות רספונסיביות
אכלוס מאפייני srcset
הוא בדרך כלל תהליך ידני פשוט, כי המאפיין מציין רק
מידע על ההגדרות שכבר הגדרתם כשיצרתם את המקורות. במשימות שלמעלה, ניסחנו
שמות הקבצים ופרטי הרוחב שבהם יופיע המאפיין:
srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w"
חשוב לזכור שהתוכן של המאפיין srcset
הוא תיאורי ולא מרשם. אין נזק בעומס יתר
srcset
, כל עוד יחס הגובה-רוחב של כל המקורות הוא עקבי. מאפיין srcset
יכול להכיל את ה-URI
והרוחב של כל חיתוך חלופי שנוצר על ידי השרת בלי לגרום לבקשות מיותרות, ולכן גם
המקורות שאנחנו מספקים לתמונה מעובדת, כך הדפדפן יוכל להתאים אישית את הבקשות בצורה יעילה יותר.
כמו שלמדתם להשתמש בתמונות רספונסיביות, מומלץ להשתמש ברכיב <picture>
כדי לטפל ב-WebP בצורה חלקה
או תבנית חלופית של JPEG. במקרה הזה, ייעשה שימוש במאפיין type
יחד עם srcset
.
<picture>
<source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
<img srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>
כמו שהבנת, דפדפנים שתומכים ב-WebP יזהו את התוכן של המאפיין type
ויבחרו את האפשרות <source>
את המאפיין srcset
של הרכיב כרשימה של הצעות לתמונות. דפדפנים שלא מזהים את image/webp
כמדיה תקפה
הסוג הזה יתעלם מה<source>
הזה, ובמקום זאת ישתמש במאפיין srcset
של הרכיב <img>
הפנימי.
יש שיקול נוסף אחד מבחינת התמיכה בדפדפן: דפדפנים שלא תומכים בתגי עיצוב של תמונות רספונסיביות
עדיין זקוקים לחלופה, או שקיים סיכון לתמונה לא תקינה בהקשרים ישנים במיוחד של גלישה. כי <picture>
,
<source>
ו-srcset
לא נלקחות בחשבון בדפדפנים אלה, נרצה לציין מקור ברירת מחדל ב-<img>
הפנימי
מאפיין src
.
מאחר ששינוי קנה מידה של תמונה כלפי מטה הוא חלקי מבחינה ויזואלית, וקידוד JPEG נתמך באופן אוניברסלי, לכן קוד ה-JPEG הגדול ביותר הוא בחירה הגיונית.
<picture>
<source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
<img src="filename-1000.jpg" srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>
ההתמודדות עם sizes
עשויה להיות קצת יותר קשה. כפי שלמדתם, sizes
הוא בהכרח לפי הקשר — אתם
לא ניתן לאכלס את המאפיין בלי לדעת את כמות השטח שהתמונה אמורה לתפוס בפריסה המעובדת. עבור
את הבקשות היעילות ביותר, מאפיין sizes
מדויק צריך להיות בתגי העיצוב שלנו בזמן שהבקשות האלה
נוצרו על ידי משתמש הקצה, הרבה לפני שהתבקשו הסגנונות שמנהלים את פריסת הדף. השמטת sizes
בסך הכול
אינה רק הפרה של מפרט ה-HTML, אלא גורמת להתנהגות ברירת מחדל שמקבילה ל-sizes="100vw"
- מידע
לדפדפן, התמונה הזו מוגבלת רק על ידי אזור התצוגה עצמו, מה שמוביל למילים האפשריות הגבוהות ביותר.
נבחר.
כמו במקרה של כל משימה מסובכת במיוחד של פיתוח אתרים, נוצרו מספר כלים כדי להפשט
תהליך הכתיבה הידנית של מאפייני sizes
. respImageLint
הוא בהחלט
קטע קוד חיוני שנועד לבדוק את הדיוק של מאפייני sizes
ולספק הצעות לשיפור.
היא פועלת כסימנייה – כלי שמופעל בדפדפן ומכוון לדף שעבר עיבוד מלא שמכיל את התמונה שלכם
רכיבים. בהקשר שבו לדפדפן יש הבנה מלאה של פריסת הדף, הוא גם יהיה כמעט מושלם
המודעות לשטח שהתמונה אמורה לתפוס בפריסה הזו בכל גודל אפשרי של אזור תצוגה.
כלי שמאפשר לאתר שגיאות בקוד של מאפייני sizes
מאוד שימושי, אבל יש לו ערך רב עוד יותר ככלי שמאפשר לייצר אותם בסיטונות.
כידוע לך, התחביר של srcset
ו-sizes
מיועד לאופטימיזציה של בקשות לנכסי תמונות באופן חזותי חלק. למרות
זה לא משהו שאי פעם צריך להשתמש בו בסביבת ייצור, ערך ברירת המחדל של placeholder של sizes
הוא 100vw
הוא סביר מאוד
בזמן העבודה על פריסת הדף בסביבת הפיתוח המקומית. אחרי שמגדירים סגנונות פריסה, יופעל respImageLint
יספק לך מאפייני sizes
מותאמים אישית שאפשר להעתיק ולהדביק בתגי העיצוב, ברמת פירוט גבוהה יותר
יותר ממסמך אחד שנכתב בכתב יד:
בקשות לתמונות שנשלחות על ידי תגי עיצוב שמעובדים על ידי השרת מתרחשות מהר מדי ולא ניתן לאפשר ל-JavaScript ליצור מאפיין sizes
בצד הלקוח, אבל
אותה נימוק לא רלוונטית אם הבקשות האלה נשלחות ביוזמת הלקוח. בפרויקט Lazysizes,
לדוגמה, מאפשר לדחות בקשות לתמונה עד לאחר שהפריסה תתבסס, מה שיאפשר ל-JavaScript ליצור
ערכי sizes
שלנו — חוויית נוחות רבה מאוד והתחייבות לבקשות היעילות ביותר האפשריות עבור המשתמשים שלך.
עם זאת, חשוב לזכור שהמשמעות של גישה זו היא שיש ויתור על המהימנות של תגי עיצוב שעובדו על ידי שרת ועל המהירות
לאופטימיזציה שמובנית בדפדפנים, והפעלת הבקשות האלה רק אחרי שהדף עובד, תהיה בגודל
השפעה שלילית על דירוג ה-LCP.
כמובן שאם אתם כבר תלויים במסגרות עיבוד בצד הלקוח, כמו React או Vue, זה חוב שכבר הייתם משלמים
תצבור — ובמקרים כאלה, שימוש ב'Lazysizes' פירושו שאפשר יהיה להשמיט את מאפייני sizes
שלך כמעט לגמרי.
איכות טובה יותר: ככל שהשימוש ב-sizes="auto"
בתמונות בטעינה מדורגת צובר קונצנזוס
בהטמעות מקוריות, Lazysizes יהפכו באופן יעיל ל-polyfill של ההתנהגות הסטנדרטית החדשה של הדפדפן.