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

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

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

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

  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`‎
'Downlink' ‎navigator.connection.downlink
'Device-Memory' ‎navigator.deviceMemory‎
פלאגינים של Imagemin לסוגי קבצים.

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

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

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

סיכום

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

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

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

משאבים

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