הסתגלות למשתמשים באמצעות רמזים ללקוחות

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

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

הכול קשור למשא ומתן על תוכן

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

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

Accept: image/webp,image/apng,image/*,*/*;q=0.8

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

<?php
// Check Accept for an "image/webp" substring.
$webp = stristr($_SERVER["HTTP_ACCEPT"], "image/webp") !== false ? true : false;

// Set the image URL based on the browser's WebP support status.
$imageFile = $webp ? "whats-up.webp" : "whats-up.jpg";
?>
<img src="<?php echo($imageFile); ?>" alt="I'm an image!">

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

הצטרפות

בניגוד לכותרת Accept, רמזים ללקוח לא מופיעים סתם כך (למעט Save-Data, שנדון בו בהמשך). כדי לצמצם את מספר כותרות הבקשה, צריך לבחור אילו רמזים מהלקוח רוצים לקבל על ידי שליחת כותרת Accept-CH כשמשתמש מבקש משאב:

Accept-CH: Viewport-Width, Downlink

הערך של Accept-CH הוא רשימה מופרדת בפסיקים של הנחיות מפורטות שהאתר ישתמש בהן כדי לקבוע את התוצאות של בקשת המשאב הבאה. כשהלקוח קורא את הכותרת הזו, הוא מקבל את ההודעה "האתר הזה רוצה את ההצעות ללקוח Viewport-Width ו-Downlink". אל תדאגו להצעות הספציפיות עצמן. תכף נטפל בהן.

אפשר להגדיר את כותרות ההסכמה האלה בכל שפת קצה עורפי. לדוגמה, אפשר להשתמש בפונקציית header של PHP. אפשר גם להגדיר את כותרות ההסכמה האלה באמצעות המאפיין http-equiv בתג <meta>:

<meta http-equiv="Accept-CH" content="Viewport-Width, Downlink" />

כל הרמזים על הלקוח!

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

טיפים לגבי מכשירים

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

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

גודל פנימי: הממדים בפועל של משאב מדיה. לדוגמה, אם פותחים תמונה ב-Photoshop, המימדים שמוצגים בתיבת הדו-שיח של גודל התמונה מתארים את הגודל הפנימי שלה.

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

<img
  src="whats-up-1x.png"
  srcset="whats-up-2x.png 2x, whats-up-1x.png 1x"
  alt="I'm that image you wanted."
/>

נניח שהגודל הפנימי של התמונה 1x במקרה הזה הוא 320x240, והגודל הפנימי של התמונה 2x הוא 640x480. אם הלקוח שמוטמע במכשיר עם יחס פיקסלים של 2 (למשל, מסך Retina) מנתח את הרכיב הזה, מתבצעת בקשה לתמונה 2x. הגודל הפנימי המותאם לצפיפות של התמונה 2x הוא 320x240, כי 640x480 חלקי 2 הוא 320x240.

גודל חיצוני: הגודל של משאב מדיה אחרי ש-CSS וגורמים אחרים של פריסה (כמו המאפיינים width ו-height) הוחלו עליו. נניח שיש לכם רכיב <img> שטוען תמונה בגודל פנימי של 320x240 עם תיקון דחיסות, אבל יש לו גם מאפייני CSS width ו-height עם הערכים 256px ו-192px, בהתאמה. בדוגמה הזו, הגודל החיצוני של רכיב <img> הופך ל-256x192.

איור של גודל פנימי לעומת גודל חיצוני. תיבה בגודל 320x240 פיקסלים עם התווית INTRINSIC

SIZE. בתוך התיבה הזו יש תיבה קטנה יותר בגודל 256x192 פיקסלים, שמייצגת רכיב img ב-HTML עם CSS שהוחל עליו. התיבה הזו מסומנת בתווית EXTRINSIC

SIZE. משמאל מוצגת תיבה שמכילה CSS שהוחל על הרכיב, שמשנה את הפריסה של רכיב ה-img כך שהגודל החיצוני שלו יהיה שונה מהגודל הפנימי שלו.
איור 1. איור של גודל פנימי לעומת גודל חיצוני. גודל התמונה החיצוני נקבע אחרי שגורמי הפריסה חלים עליה. במקרה הזה, אם מחילים את כללי ה-CSS של width: 256px; ושל height: 192px;, התמונה בגודל פנימי של 320x240 הופכת לתמונה בגודל חיצוני של 256x192.

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

Viewport-Width

Viewport-Width הוא רוחב אזור התצוגה של המשתמש בפיקסלים של CSS:

Viewport-Width: 320

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

DPR

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

DPR: 2

הרמז הזה שימושי כשבוחרים מקורות של תמונות שתואמים לדחיסות הפיקסלים של המסך (כמו שמתארי x עושים זאת במאפיין srcset).

רוחב

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

לדוגמה, נניח שמשתמש מבקש דף עם מסך ברוחב 320 פיקסלים ב-CSS ועם DPR של 2. המכשיר טוען מסמך עם רכיב <img> שמכיל ערך למאפיין sizes של 85vw (כלומר, 85% מרוחב אזור התצוגה בכל גודלי המסכים). אם הלקוח הביע הסכמה להשתמש ברמזו של Width, הוא ישלח את הרמזו הזה של Width לשרת עם הבקשה ל-src של <img>:

Width: 544

במקרה כזה, הלקוח נותן לשרת רמז לרוחב המובנה האופטימלי של התמונה המבוקשת, שהוא 85% מרוחב חלון הצפייה (272 פיקסלים) כפול DPR של המסך (2), שווה ל-544 פיקסלים.

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

Content-DPR

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

בשונה מרמזים אחרים של הלקוח, Content-DPR היא לא כותרת בקשה לשימוש השרתים. במקום זאת, שרתי כותרות של תשובה חייבים לשלוח בכל פעם שמשתמשים ברמזים של DPR ו-Width כדי לבחור משאב. הערך של Content-DPR צריך להיות תוצאה של המשוואה הזו:

Content-DPR = [הגודל של משאב התמונה שנבחר] / ([Width] / [DPR])

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

Device-Memory

מבחינה טכנית, Device-Memory הוא חלק מ-Device Memory API, והוא חושף את הכמות המשוערת של הזיכרון במכשיר הנוכחי ב-GiB:

Device-Memory: 2

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

הנחיות לגבי רשתות

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

RTT

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

RTT: 125

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

זמן האחזור חשוב לביצועי הטעינה, אבל גם רוחב הפס משפיע. ההצעה Downlink, שמוצגת במגה-בייט לשנייה (Mbps), חושפת את מהירות ההורדה המשוערת של החיבור של המשתמש:

Downlink: 2.5

בשילוב עם RTT, אפשר להשתמש ב-Downlink כדי לשנות את אופן העברת התוכן למשתמשים על סמך איכות החיבור לרשת.

שעון אקוודור

ההצעה ECT מייצגת את סוג החיבור בפועל. הערך שלו הוא אחד מתוך רשימה מפורטת של סוגי חיבורים, שכל אחד מהם מתאר חיבור בתוך טווחים ספציפיים של הערכים RTT וגם Downlink.

הכותרת הזו לא מסבירה מהו סוג החיבור האמיתי – לדוגמה, היא לא מדווחת אם השער הוא מגדל סלולרי או נקודת גישה ל-Wi-Fi. במקום זאת, המערכת מנתחת את זמן האחזור ורוחב הפס של החיבור הנוכחי ומחליטה לאיזה פרופיל רשת הוא דומה ביותר. לדוגמה, אם מתחברים לרשת איטית באמצעות Wi-Fi, יכול להיות שהערך של ECT יהיה 2g, שהוא הערך הקרוב ביותר לחיבור היעיל:

ECT: 2g

הערכים החוקיים של ECT הם 4g,‏ 3g,‏ 2g ו-slow-2g. אפשר להשתמש בהצעה הזו כנקודת התחלה להערכת איכות החיבור, ולאחר מכן לשפר אותה באמצעות ההצעות RTT ו-Downlink.

Save-Data

הערך Save-Data הוא לא רק רמז שמתאר את תנאי הרשת, אלא העדפת משתמש שמציינת שדפים צריכים לשלוח פחות נתונים.

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

Save-Data: on

אצלנו ב-Google, דיברנו על מה שאפשר לעשות עם Save-Data. ההשפעה על הביצועים עשויה להיות משמעותית. זה סימן לכך שהמשתמשים ממש מבקשים מכם לשלוח להם פחות דברים! אם תקשיבו לאות הזה ותפעלו בהתאם, המשתמשים יעריכו את זה.

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

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

תמונות רספונסיביות

כל התרחישים לדוגמה של שימוש בתמונות רספונסיביות, מלבד התרחישים הפשוטים ביותר, יכולים להיות מורכבים. מה קורה אם יש לכם כמה טיפולים וווריאציות של אותן תמונות לגדלים שונים של מסכים – ובפורמטים שונים? הרכיבים האלה של ה-Markup הופכים למורכבים מאוד מהר. קל לטעות, וקל לשכוח או להבין בצורה שגויה מושגים חשובים (כמו sizes).

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

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

  1. אם זה רלוונטי לתהליך העבודה שלכם, קודם צריך לבחור עיבוד תמונה (כלומר תמונות עם עיצוב גרפי) על ידי סימון ההצעה Viewport-Width.
  2. כדי לבחור רזולוציית תמונה, בודקים את הרמז Width ואת הרמז DPR, ובוחרים מקור שמתאים לגודל הפריסה ולצפיפות המסך של התמונה (בדומה לאופן שבו פועלים התיאורים x ו-w ב-srcset).
  3. צריך לבחור את פורמט הקובץ הכי אופטימלי שנתמך בדפדפן (דרך Accept עוזרת לנו ברוב הדפדפנים).

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

<picture>
  <source
    srcset="
      company-photo-256w.webp   256w,
      company-photo-512w.webp   512w,
      company-photo-768w.webp   768w,
      company-photo-1024w.webp 1024w,
      company-photo-1280w.webp 1280w
    "
    type="image/webp"
  />
  <img
    srcset="
      company-photo-256w.jpg   256w,
      company-photo-512w.jpg   512w,
      company-photo-768w.jpg   768w,
      company-photo-1024w.jpg 1024w,
      company-photo-1280w.jpg 1280w
    "
    src="company-photo-256w.jpg"
    sizes="(min-width: 560px) 251px, 88.43vw"
    alt="The Sconnie Timber Staff!"
  />
</picture>

הצלחתי לצמצם את הרשימה לאפשרויות הבאות על סמך התמיכה בדפדפנים השונים:

<img
  src="/image/sizes:true/company-photo.jpg"
  sizes="(min-width: 560px) 251px, 88.43vw"
  alt="SAY CHEESY PICKLES."
/>

בדוגמה הזו, כתובת ה-URL /image היא סקריפט PHP שמופיע אחרי פרמטרים שנכתבו מחדש על ידי mod_rewrite. הוא מקבל שם קובץ של תמונה ופרמטרים נוספים כדי לעזור לסקריפט לקצה העורפי לבחור את התמונה הטובה ביותר בתנאים הנתונים.

אני מניח שהשאלה הראשונה שלך היא "האם זו לא רק הטמעה מחדש של <picture> ו-srcset בקצה העורפי?"

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

בעזרת טיפים ללקוחות, אפשר להתחיל בתמונה ברזולוציה גבוהה ללא אובדן נתונים, שאפשר לשנות את הגודל שלה באופן דינמי כך שתתאים לכל שילוב כל של מסך ופריסה. בניגוד ל-srcset, שבו צריך לפרט רשימה קבועה של תמונות אפשריות שהדפדפן יכול לבחור מתוכן, הגישה הזו יכולה להיות גמישה יותר. בעוד שהשימוש ב-srcset מאלץ אתכם להציע לדפדפנים קבוצה גסה של וריאציות – למשל, 256w,‏ 512w,‏ 768w ו-1024w – פתרון שמבוסס על רמזים מהלקוח יכול להציג את כל הרוחבים, בלי ערימה ענקית של רכיבי Markup.

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

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

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

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

לגבי האתר של Sconnie Timber, אנחנו מבצעים פעולות כדי להקל על העומס כשהרשתות איטיות, ומתבצעת בדיקה של הכותרות Save-Data,‏ ECT,‏ RTT ו-Downlink בקוד הקצה העורפי שלנו. לאחר מכן, אנחנו יוצרים ציון של איכות הרשת, שבעזרתו אנחנו יכולים לקבוע אם כדאי לנו להתערב כדי לשפר את חוויית המשתמש. ציון הרשת הזה הוא בין 0 ל-1, כאשר 0 היא איכות הרשת הגרועה ביותר האפשרית, ו-1 היא הטובה ביותר.

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

עם זאת, אם הפרמטר Save-Data חסר, נמשיך לשלב את הערכים של הרמזים ECT, RTT ו-Downlink כדי לחשב ציון שמתאר את איכות החיבור לרשת. קוד המקור ליצירת ציון הרשת זמין ב-GitHub. המסקנה היא שאם נשתמש בטיפים הקשורים לרשת באופן כלשהו, נוכל לשפר את החוויה של משתמשים ברשתות איטיות.

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

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

בדוגמה הזו אפשר לראות את ההשפעה של רמזים ללקוח על שיפור הביצועים של אתרים ברשתות איטיות יותר. בהמשך מוצגת תצוגת מפל של WebPagetest לאתר ברשת איטית שלא מתאימה לטיפים של הלקוח:

תרשים &#39;מפל&#39; של WebPagetest לאתר Sconnie Timber, שבו נטענים כל המשאבים בחיבור איטי לרשת.
איור 3. אתר עם משאבים רבים שטעון תמונות, סקריפטים וגופנים בחיבור איטי.

עכשיו תרשים Waterfall של אותו אתר באותו חיבור איטי, אלא שבפעם הזו האתר משתמש בטיפים ללקוח כדי להסיר משאבי דף לא קריטיים:

תרשים &#39;מפל&#39; של WebPagetest לאתר Sconnie Timber, שבו נעשה שימוש ברמזי לקוח כדי להחליט לא לטעון משאבים לא קריטיים בחיבור איטי לרשת.
איור 4. אותו אתר באותו חיבור, רק המשאבים 'שטוב שיש' לא נכללים כדי לאפשר טעינה מהירה יותר.

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

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

// Set the ECT value to "4g" by default.
$ect = isset($_SERVER["HTTP_ECT"]) ? $_SERVER["HTTP_ECT"] : "4g";

כאן, "4g" מייצג את חיבור הרשת באיכות הגבוהה ביותר שהכותרת ECT מתארת. אם נאיץ את $ect ל-"4g", דפדפנים שלא תומכים בטיפים ללקוח לא יושפעו. הצטרפות FTW!

חשוב לשים לב למטמון!

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

Vary: DPR, Width

עם זאת, יש לכך אזהרה גדולה: לעולם אל תשתמשו ב-Vary כדי לשמור בתגובה שניתנת לשמירה במטמון בכותרת שמשתנה לעיתים קרובות (כמו Cookie), כי המשאבים האלה הופכים למעשה לבלתי ניתנים לשמירה במטמון. על סמך המידע הזה כדאי להימנע מVaryכותרות של הרמזים של לקוח, כמו RTT או Downlink, כי אלו גורמי חיבור שעשויים להשתנות לעיתים קרובות. אם רוצים לשנות את התשובות בכותרות האלה, כדאי לשמור רק את הכותרת ECT, כדי לצמצם את החסרות במטמון.

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

רמזים על הלקוח (Client Hints) בשירותי העבודה

משא ומתן על תוכן כבר לא מיועד רק לשרתים! מכיוון ששירותי העבודה פועלים בתור שרתים proxy בין לקוחות לשרתים, יש לכם שליטה על האופן שבו המשאבים מועברים באמצעות JavaScript. כולל רמזים ללקוח. באירוע fetch של ה-service worker, אפשר להשתמש ב-method‏ request.headers.get של האובייקט event כדי לקרוא את כותרות הבקשה של המשאב באופן הבא:

self.addEventListener('fetch', (event) => {
  let dpr = event.request.headers.get('DPR');
  let viewportWidth = event.request.headers.get('Viewport-Width');
  let width = event.request.headers.get('Width');

  event.respondWith(
    (async function () {
      // Do what you will with these hints!
    })(),
  );
});

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

רמז ללקוח המקבילה ב-JS
'ECT' ‎`navigator.connection.effectiveType`‎
RTT ‎`navigator.connection.rtt`‎
‎'Save-Data'‎ `navigator.connection.saveData`
'קישור למטה' `navigator.connection.downlink`
'Device-Memory' `navigator.deviceMemory`
יישומי הפלאגין של Imagemin לסוגי קבצים.

מכיוון שממשקי ה-API האלה לא זמינים בכל מקום שבו צריך לבדוק את התכונות, מומלץ לבדוק את התכונות באמצעות האופרטור in:

if ('connection' in navigator) {
  // Work with netinfo API properties in JavaScript!
}

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

סיכום

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

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

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

משאבים

תודה ל-Ilya Grigorik, ל-Eric Portis, ל-Jeff Posnick, ל-Yoav Weiss ול-Estelle Weyl על המשוב והעריכה החשובים שלהם במאמר הזה.