כאן אפשר להבין מהו השהיה לאחר קלט וללמד שיטות להפחתת הזמן הזה, כדי לאפשר אינטראקטיביות מהירה יותר.
אינטראקציות באינטרנט הן דברים מורכבים, וכל סוגי הפעילות שמתרחשים בדפדפן מתרחשות כדי להניע אותם. עם זאת, המשותף לכולם הוא שהם חווים עיכוב מסוים בקלט לפני שהקריאות החוזרות של האירועים שלהם מתחילות לפעול. במדריך הזה נסביר מהו עיכוב קלט, ומה אפשר לעשות כדי למזער אותו כדי שהאינטראקציות באתר יפעלו מהר יותר.
מהו השהיה לאחר קלט?
עיכוב בקלט הוא פרק הזמן שמתחיל מהאינטראקציה הראשונה של המשתמש עם דף כלשהו (למשל: הקשה על מסך, לחיצה עם העכבר או לחיצה על מקש) ועד לרגע שבו מתחיל האירוע הקריאה החוזרת (callback) של האירוע עבור האינטראקציה. כל אינטראקציה מתחילה עם עיכוב מסוים של קלט.
חלק מסוים מהעיכוב בקלט הוא בלתי נמנע: תמיד לוקח למערכת ההפעלה זמן לזהות אירוע קלט ולהעביר אותו לדפדפן. עם זאת, החלק הזה של עיכוב הקלט בדרך כלל לא מורגש. יש דברים אחרים שקורים בדף עצמו שעלולים לגרום לעיכובים בקלט להיות ארוכים מספיק כדי לגרום לבעיות.
מה צריך לדעת על עיכוב קלט?
באופן כללי, כדאי להקפיד שכל חלק באינטראקציה יהיה קצר ככל האפשר, כדי לשפר את הסיכוי שהאתר יעמוד במדד 'מהירות אינטראקציה עד התגובה הבאה' (INP) כ'טוב'. הסף, בלי קשר למכשיר של המשתמש. שמירה על ההשהיה של הקלט בבדיקת היא רק חלק אחד מעמידה בסף הזה.
כלומר, כדאי לשאוף לעיכוב הקצר ביותר שאפשר לקבל כדי להגיע למדד 'טוב' לסף מסוים. עם זאת, חשוב לדעת שלא צפויים ביטול מוחלט של עיכובים בקלט. כל עוד אתם נמנעים מעבודה רבה מדי על ה-thread הראשי בזמן שהמשתמשים מנסים לבצע אינטראקציה עם הדף, ההשהיה בקלט צריכה להיות נמוכה מספיק כדי למנוע בעיות.
איך לצמצם את ההשהיה לפני הקלט
כפי שציינו קודם, עיכוב מסוים בקלט הוא בלתי נמנע, אבל מנגד, ניתן למנוע עיכוב מסוים בקלט. הנה כמה דברים שכדאי לשקול אם מתקשים בעיכובים ארוכים בקלט.
להימנע מטיימרים חוזרים שמפעילים הרבה עבודה בשרשור הראשי
יש שתי פונקציות טיימר נפוצות ב-JavaScript שיכולות לגרום לעיכוב בקלט: setTimeout
ו-setInterval
. ההבדל בין שתי השיטות הוא ש-setTimeout
מתזמנת קריאה חוזרת (callback) שתרוץ אחרי פרק זמן מסוים. לעומת זאת, setInterval
מתזמנת קריאה חוזרת (callback) שתרוץ כל n אלפיות השנייה באופן קבוע, או עד שהטיימר יופסק ב-clearInterval
.
setTimeout
לא בעייתית בפני עצמה, אבל למעשה היא יכולה לעזור להימנע ממשימות ארוכות. עם זאת, הזמן הזה תלוי במועד שבו הזמן הקצוב לתפוגה יסתיים, ובשאלה אם המשתמש ינסה לבצע אינטראקציה עם הדף במהלך הפעלת הקריאה החוזרת (callback) של הזמן הקצוב לתפוגה.
בנוסף, אפשר להריץ את setTimeout
בלולאה או באופן רקורסיבי, ואז היא תפעל יותר כמו setInterval
, אבל עדיף שלא לתזמן את האיטרציה הבאה עד להשלמת האיטרציה הקודמת. במילים אחרות, הלולאה תפיק ל-thread הראשי בכל פעם שיש קריאה ל-setTimeout
, אבל כדאי לוודא שהקריאה החוזרת שלו לא גורמת לעומס רב מדי.
setInterval
מריץ קריאה חוזרת (callback) במרווח זמן מסוים, ולכן יש סיכוי גבוה יותר שיפריע לאינטראקציות. הסיבה לכך היא שבניגוד למופע אחד של קריאה ל-setTimeout
, שהיא קריאה חוזרת חד-פעמית שעשויה להפריע לאינטראקציה של משתמש – האופי החוזר של setInterval
מעלה את הסבירות שהיא יפריע לאינטראקציה, דבר שיגדיל את עיכוב הקלט של האינטראקציה.
אם הטיימרים פועלים בקוד מאינטראקציה ישירה (First-Party), אתם יכולים לשלוט בהם. חשבו אם אתם צריכים אותן או עשו כמיטב יכולתכם כדי לצמצם את העבודה עליהן ככל האפשר. עם זאת, הטיימרים בסקריפטים של צד שלישי הם שונים לגמרי. לרוב אין לכם שליטה על הפעולות שעושים סקריפט של צד שלישי. לעיתים קרובות, כדי לתקן בעיות בביצועים של קוד של צד שלישי צריך לעבוד עם בעלי עניין כדי להבין אם יש צורך בסקריפט של צד שלישי. אם כן, תצטרכו ליצור קשר עם ספק סקריפטים של צד שלישי כדי לברר מה אפשר לעשות כדי לפתור בעיות בביצועים שהוא עלול לגרום לאתר.
להימנע ממשימות ארוכות
אחת הדרכים לצמצם עיכובים ארוכים בקלט היא להימנע ממשימות ארוכות. כשיש עבודה מיותרת על ה-thread הראשי שחוסמת את ה-thread הראשי במהלך אינטראקציות, היא מוסיפה לעיכוב הקלט שלהם לפני שהמשימות הארוכות הסתיימו.
חוץ מצמצום כמות העבודה שאתם מבצעים במשימה, ואתם צריכים תמיד להשקיע כמה שפחות בעבודה בשרשור הראשי, תוכלו לשפר את מהירות התגובה לקלט של משתמשים על ידי פיצול של משימות ארוכות.
היזהרו מאינטראקציות חופפות
חלק מאתגר במיוחד באופטימיזציה של INP יכול להיות אם יש אינטראקציות חופפות. המשמעות של חפיפה בין אינטראקציות היא שלאחר אינטראקציה עם רכיב אחד, אתה מבצע אינטראקציה נוספת עם הדף לפני שהאינטראקציה הראשונית הספיקה כדי לעבד את המסגרת הבאה.
מקורות החפיפה של אינטראקציות יכולים להיות פשוטים כמו משתמשים שמבצעים אינטראקציות רבות בפרק זמן קצר. מצב זה עשוי להתרחש כאשר משתמשים מקלידים בשדות טופס, שבהם עשויות להתרחש אינטראקציות רבות עם המקלדת בפרק זמן קצר מאוד. אם העבודה על אירוע מרכזי יקרה במיוחד, כמו במקרה הנפוץ של שדות השלמה אוטומטית שבהם בקשות רשת נשלחות לקצה עורפי – יש לכם שתי אפשרויות:
- כדאי לשקול עזיבה מהדף הראשון של ערכי קלט כדי להגביל את מספר הפעמים שקריאה חוזרת (callback) של אירוע מופעלת בפרק זמן נתון.
- אפשר להשתמש בפונקציה
AbortController
כדי לבטל בקשות יוצאות שלfetch
, כדי שלא יהיה עומס ב-thread הראשי כדי לטפל בקריאות חוזרות שלfetch
. הערה: אפשר להשתמש במאפייןsignal
של מופעAbortController
גם כדי לבטל אירועים.
מקור נוסף לעיכוב מוגבר בקלט עקב אינטראקציות חופפות יכולות להיות אנימציות יקרות. באופן ספציפי, אנימציות ב-JavaScript עשויות להפעיל קריאות רבות של requestAnimationFrame
, שעשויות להפריע לאינטראקציות של המשתמשים. כדי לעקוף את הבעיה, כדאי להשתמש באנימציות CSS כשאפשר, כדי להימנע מהוספת מסגרות אנימציה לרשימת 'הבאים בתור' שעשויות להיות יקרות. אם עושים זאת, חשוב להימנע מאנימציות לא מורכבות, כדי שהאנימציות יפעלו בעיקר בשרשורים של ה-GPU ושל הקומפוזבילי, ולא בשרשור הראשי.
סיכום
אמנם לא בטוח שהזמן שנדרש לקליטת נתונים מייצג את רוב הזמן שנדרש לאינטראקציות, אבל חשוב להבין שכל חלק באינטראקציה לוקח זמן שניתן לקצר. אם אתם צופים בעיכוב ארוך של הקלט, יש לכם הזדמנויות להפחית אותו. כדי לצמצם את העיכובים בזמני הקלט, כדאי להימנע מהתקשרות חוזרת (callback) חוזרות של הטיימר, חלוקת משימות ארוכות ומוּדעוּת לחפיפה פוטנציאלית בין אינטראקציות, וכך לשפר את האינטראקטיביות של המשתמשים באתר.
תמונה ראשית (Hero) מ-Unbounce, מאת Erik Mclean.