התאמה למשתמשים באמצעות איסוף אותות בצד הלקוח

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

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

Width: 544

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

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

Content-DPR

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

בניגוד ל-Client Hints אחרים, Content-DPR היא לא כותרת בקשה ששרתים משתמשים בה, אלא כותרת תגובה ששרתים חייבים לשלוח בכל פעם שמשתמשים ב-Client Hints מסוג 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, חברת עץ בדיונית שנמצאת באזור כפרי בצפון-מערב ארה"ב. כמו שקורה לעיתים קרובות באזורים מרוחקים, החיבורים לרשת יכולים להיות לא יציבים. כאן טכנולוגיה כמו איסוף אותות בצד הלקוח יכולה לעשות הבדל משמעותי למשתמשים.

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

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

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

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

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

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

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

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

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

תרשים מפל של WebPagetest באתר Sconnie Timber, שמשתמש ב-Client Hints כדי להחליט לא לטעון משאבים לא קריטיים בחיבור איטי לרשת.
איור 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.

איסוף אותות בצד הלקוח בקובצי שירות (Service Workers)

משא ומתן על תוכן כבר לא מיועד רק לשרתים. מכיוון שקובצי השירות פועלים כשרתי 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!
}

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

כמעט סיימנו

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

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

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

משאבים

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