איך מבצעים אופטימיזציה של זמן האינטראקציה עד התוכן הבא באתר
פורסם: 19 במאי 2023, עדכון אחרון: 9 בספטמבר 2025
מהירות התגובה לאינטראקציה באתר (INP) הוא מדד יציב של מדדים בסיסיים של חוויית המשתמש באתר. המדד הזה מעריך את רמת הרספונסיביות הכוללת של דף לאינטראקציות של משתמשים, על ידי מעקב אחר זמן האחזור של כל האינטראקציות שעומדות בדרישות שמתרחשות במהלך משך החיים של ביקור משתמש בדף. ערך ה-INP הסופי הוא משך הזמן הארוך ביותר של אינטראקציה שזוהה (לפעמים ללא חריגים חשודי טעות).
כדי לספק חוויית משתמש טובה, מומלץ שמהירות התגובה לאינטראקציה באתר (INP) תהיה 200 מילישניות או פחות. כדי לעמוד ביעד הזה עבור רוב המשתמשים, סף טוב למדידה הוא האחוזון ה-75 של טעינות הדפים, מפולח לפי מכשירים ניידים ומחשבים.
יכול להיות שיהיו באתר מעט אינטראקציות או שלא יהיו בכלל – למשל, דפים שכוללים בעיקר טקסט ותמונות, עם מעט רכיבים אינטראקטיביים או ללא רכיבים כאלה. לחלופין, באתרים כמו עורכי טקסט או משחקים, יכולות להיות מאות ואפילו אלפי אינטראקציות. בכל מקרה, אם ערך ה-INP גבוה, חוויית המשתמש עלולה להיפגע.
שיפור מדד INP דורש זמן ומאמץ, אבל התגמול הוא חוויית משתמש טובה יותר. במדריך הזה נסביר איך לשפר את מדד INP.
איך מבררים מה גורם לערך INP נמוך
כדי לפתור בעיות שקשורות לאינטראקציות איטיות, צריך נתונים שיצביעו על כך שערך ה-INP של האתר נמוך או שצריך לשפר אותו. אחרי שמקבלים את המידע הזה, אפשר לעבור למעבדה כדי להתחיל לאבחן אינטראקציות איטיות ולמצוא פתרון.
איתור אינטראקציות איטיות בשטח
מומלץ להתחיל את תהליך האופטימיזציה של INP עם נתונים מהשטח. במקרה הטוב, נתוני השדה מספק Real User Monitoring (RUM) יציגו לכם לא רק את ערך ה-INP של הדף, אלא גם נתונים הקשריים שמדגישים איזו אינטראקציה ספציפית אחראית לערך ה-INP עצמו, אם האינטראקציה התרחשה במהלך טעינת הדף או אחריה, סוג האינטראקציה (קליק, הקשה על מקש או הקשה) ומידע חשוב אחר.
אם אתם לא מסתמכים על ספק RUM כדי לקבל נתוני שטח, במדריך לנתוני שטח של INP מומלץ להשתמש בכלי PageSpeed Insights כדי להציג את הנתונים של הדוח לגבי חוויית המשתמש ב-Chrome (CrUX), כדי לעזור לכם להשלים את הפערים. CrUX הוא מערך הנתונים הרשמי של תוכנית מדדי הליבה לבדיקת חוויית המשתמש באתר, והוא מספק סיכום ברמה גבוהה של מדדים למיליוני אתרים, כולל INP. עם זאת, CrUX לא מספק לעיתים קרובות את הנתונים ההקשריים שמתקבלים מספק RUM, שיכולים לעזור לכם לנתח בעיות. לכן, אנחנו עדיין ממליצים לאתרים להשתמש בספק RUM כשאפשר, או להטמיע פתרון RUM משלהם כדי להשלים את מה שזמין ב-CrUX.
אבחון אינטראקציות איטיות במעבדה
מומלץ להתחיל לבצע בדיקות במעבדה אחרי שיש לכם נתונים מהשטח שמצביעים על אינטראקציות איטיות. אם אין נתונים מהשטח, יש כמה אסטרטגיות לזיהוי אינטראקציות איטיות במעבדה. האסטרטגיות האלה כוללות מעקב אחרי תהליכי משתמש נפוצים ובדיקת אינטראקציות לאורך הדרך, וגם אינטראקציה עם הדף במהלך הטעינה – כשהשרשור הראשי בדרך כלל הכי עמוס – כדי לזהות אינטראקציות איטיות במהלך החלק הקריטי הזה בחוויית המשתמש.
אופטימיזציה של אינטראקציות
אחרי שמזהים אינטראקציה איטית ואפשר לשחזר אותה באופן ידני במעבדה, השלב הבא הוא לבצע אופטימיזציה שלה.
אפשר לחלק את האינטראקציות לשלושה חלקים:
- השהיה לאחר קלט ראשוני, שמתחילה כשהמשתמש יוזם אינטראקציה עם הדף ומסתיימת כשהפונקציות להחזרת ערכים של האירוע מתחילות לפעול.
- משך העיבוד, שכולל את הזמן שנדרש להפעלת קריאות חוזרות לאירועים עד להשלמתן.
- השהיית ההצגה, כלומר הזמן שנדרש לדפדפן כדי להציג את הפריים הבא שמכיל את התוצאה הוויזואלית של האינטראקציה.
הסכום של שלושת חלקי המשנה האלה הוא זמן האחזור הכולל של האינטראקציה. כל חלק משני של אינטראקציה תורם כמות מסוימת של זמן לזמן האחזור הכולל של האינטראקציה, ולכן חשוב לדעת איך אפשר לבצע אופטימיזציה של כל חלק באינטראקציה כדי שהיא תפעל כמה שפחות זמן.
זיהוי והפחתה של השהיה לאחר קלט
כשמשתמש מבצע אינטראקציה עם דף, החלק הראשון של האינטראקציה הזו הוא השהיה לאחר קלט ראשוני. בהתאם לפעילות אחרת בדף, יכול להיות שיהיו עיכובים ארוכים בהזנת הנתונים. יכול להיות שהסיבה לכך היא פעילות שמתרחשת ב-thread הראשי (אולי בגלל טעינה, ניתוח והידור של סקריפטים), טיפול באחזור, פונקציות של טיימר או אפילו אינטראקציות אחרות שמתרחשות ברצף מהיר וחופפות זו לזו.
לא משנה מה המקור של עיכוב הקלט באינטראקציה, כדאי לצמצם את עיכוב הקלט למינימום כדי שהאינטראקציות יוכלו להתחיל להפעיל את קריאות החזרה (callback) של האירועים בהקדם האפשרי.
הקשר בין הערכת סקריפט לבין משימות ארוכות במהלך ההפעלה
היבט קריטי של אינטראקטיביות במחזור החיים של הדף הוא במהלך ההפעלה. כשדף נטען, הוא עובר עיבוד ראשוני, אבל חשוב לזכור שגם אם דף עבר עיבוד, זה לא אומר שהטעינה שלו הסתיימה. בהתאם למספר המשאבים שדף צריך כדי להיות פעיל באופן מלא, יכול להיות שמשתמשים ינסו לבצע אינטראקציה עם הדף בזמן שהוא עדיין נטען.
אחד הדברים שיכולים להאריך את עיכוב הקלט של אינטראקציה בזמן טעינת דף הוא הערכת סקריפט. אחרי שקובץ JavaScript מאוחזר מהרשת, הדפדפן עדיין צריך לבצע פעולות לפני שקוד ה-JavaScript יכול לפעול. הפעולות האלה כוללות ניתוח של סקריפט כדי לבדוק שהתחביר שלו תקין, הידור שלו לקוד בייט ואז הפעלה שלו.
בהתאם לגודל הסקריפט, העבודה הזו יכולה ליצור משימות ארוכות בשרשור הראשי, שיגרמו לעיכוב בתגובה של הדפדפן לאינטראקציות אחרות של המשתמשים. כדי שהדף יגיב לקלט של המשתמשים במהלך טעינת הדף, חשוב להבין מה אפשר לעשות כדי להפחית את הסיכוי למשימות ארוכות במהלך טעינת הדף, וכך לשמור על מהירות התגובה של הדף.
אופטימיזציה של קריאות חוזרות (callbacks) של אירועים
השהיה לאחר קלט ראשוני היא רק החלק הראשון של מה שנמדד על ידי INP. בנוסף, צריך לוודא שקריאות החזרה (callbacks) של אירועים שמופעלות בתגובה לאינטראקציה של משתמש יושלמו כמה שיותר מהר.
העברה ל-Thread הראשי לעיתים קרובות
ההמלצה הכללית הכי טובה לאופטימיזציה של קריאות חוזרות (callback) לאירועים היא לבצע בהן כמה שפחות פעולות. עם זאת, יכול להיות שהלוגיקה של האינטראקציה מורכבת, ושאפשר רק להפחית באופן שולי את העבודה שהם מבצעים.
אם זה המצב באתר שלכם, השלב הבא הוא לנסות לפצל את העבודה בפונקציות הקריאה החוזרת (callback) של האירועים למשימות נפרדות. כך נמנעת הפיכת העבודה המשותפת למשימה ארוכה שחוסמת את ה-thread הראשי, ומתאפשרות אינטראקציות אחרות שהיו ממתינות ב-thread הראשי, לרוץ מוקדם יותר.
setTimeout
היא דרך אחת לפצל משימות, כי הקריאה החוזרת שמועברת אליה פועלת במשימה חדשה. אפשר להשתמש בפונקציה setTimeout
בפני עצמה או להשתמש בה באופן מופשט בפונקציה נפרדת כדי להשיג תפוקה ארגונומית יותר.
עדיף להעביר את השליטה ל-main thread באופן לא סלקטיבי מאשר לא להעביר אותה בכלל. עם זאת, יש דרך מתוחכמת יותר להעביר את השליטה ל-main thread, והיא כוללת העברה מיידית רק אחרי קריאה חוזרת (callback) של אירוע שמעדכן את ממשק המשתמש, כדי שהלוגיקה של הרינדור תוכל לפעול מוקדם יותר.
העברת השליטה כדי לאפשר עבודת רינדור מוקדמת יותר
טכניקה מתקדמת יותר של העברת שליטה כוללת מבנה של הקוד בפונקציות הקריאה החוזרת של האירועים, כדי להגביל את מה שמופעל רק ללוגיקה שנדרשת להחלת עדכונים חזותיים עבור הפריים הבא. כל השאר אפשר לדחות למשימה הבאה. הגישה הזו לא רק שומרת על קלות וגמישות של הקוד של פונקציות ה-callback, אלא גם משפרת את זמן העיבוד של האינטראקציות, כי היא לא מאפשרת לעדכונים חזותיים לחסום את הקוד של פונקציות ה-callback של האירועים.
לדוגמה, דמיינו כלי לעריכת טקסט עשיר שמבצע עיצוב של הטקסט בזמן ההקלדה, אבל גם מעדכן היבטים אחרים של ממשק המשתמש בתגובה למה שכתבתם (כמו ספירת מילים, הדגשה של שגיאות איות ומשוב חזותי חשוב אחר). בנוסף, יכול להיות שהאפליקציה תצטרך לשמור את מה שכתבתם, כדי שאם תצאו ותחזרו לא תאבדו את העבודה.
בדוגמה הזו, ארבעת הדברים הבאים צריכים לקרות בתגובה לתווים שהמשתמש הקליד. עם זאת, צריך לבצע רק את הפריט הראשון לפני שהפריים הבא מוצג.
- מעדכנים את תיבת הטקסט עם מה שהמשתמש הקליד ומחילים את העיצוב הנדרש.
- עדכון החלק בממשק המשתמש שבו מוצג מספר המילים הנוכחי.
- הפעלת לוגיקה לבדיקת שגיאות איות.
- שומרים את השינויים האחרונים (באופן מקומי או במסד נתונים מרוחק).
הקוד לביצוע הפעולה הזו יכול להיראות כך:
textBox.addEventListener('input', (inputEvent) => {
// Update the UI immediately, so the changes the user made
// are visible as soon as the next frame is presented.
updateTextBox(inputEvent);
// Use `setTimeout` to defer all other work until at least the next
// frame by queuing a task in a `requestAnimationFrame()` callback.
requestAnimationFrame(() => {
setTimeout(() => {
const text = textBox.textContent;
updateWordCount(text);
checkSpelling(text);
saveChanges(text);
}, 0);
});
});
בתרשים הבא אפשר לראות איך דחייה של עדכונים לא קריטיים עד אחרי הפריים הבא יכולה לקצר את משך העיבוד וכך להפחית את זמן האחזור הכולל של האינטראקציה.

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

הבעיה של שיבוש הפריסה היא צוואר בקבוק בביצועים, כי כשמעדכנים סגנונות ואז מבקשים מיד את הערכים של הסגנונות האלה ב-JavaScript, הדפדפן נאלץ לבצע עבודת פריסה סינכרונית, שאחרת הוא היה יכול לחכות ולבצע אותה באופן אסינכרוני מאוחר יותר, אחרי שפונקציות ה-callback של האירועים יסיימו לפעול.
צמצום העיכוב בהצגת התגובה
השהיית ההצגה של אינטראקציה מציינת את משך הזמן שחל מסיום ההפעלה של קריאות החזרה (callback) של אירוע אינטראקציה ועד לנקודה שבה הדפדפן יכול לצייר את הפריים הבא שמציג את השינויים הוויזואליים שנובעים מהאינטראקציה.
מזעור גודל ה-DOM
כשמודל ה-DOM של דף קטן, בדרך כלל עבודת הרינדור מסתיימת במהירות. עם זאת, כשמסמכי ה-DOM גדולים מאוד, עבודת הרינדור נוטה לגדול עם הגדלת גודל ה-DOM. הקשר בין עבודת הרינדור לבין גודל ה-DOM הוא לא ליניארי, אבל רינדור של DOM גדול דורש יותר עבודה מאשר רינדור של DOM קטן. גודל DOM גדול הוא בעייתי בשני מקרים:
- במהלך העיבוד הראשוני של הדף, כש-DOM גדול דורש הרבה עבודה כדי לעבד את המצב הראשוני של הדף.
- בתגובה לאינטראקציה של משתמש, שבה DOM גדול יכול לגרום לעדכוני רינדור יקרים מאוד, ולכן להגדיל את הזמן שנדרש לדפדפן להציג את הפריים הבא.
חשוב לזכור שיש מקרים שבהם אי אפשר לצמצם באופן משמעותי מסמכי DOM גדולים. יש גישות שבהן אפשר להשתמש כדי להקטין את גודל ה-DOM, כמו השטחת ה-DOM או הוספה ל-DOM במהלך אינטראקציות עם המשתמשים כדי לשמור על גודל ה-DOM הראשוני קטן, אבל הטכניקות האלה יכולות לעזור רק במידה מסוימת.
שימוש ב-content-visibility
כדי לבצע רינדור עצל של רכיבים שלא מוצגים במסך
אחת הדרכים להגביל את כמות עבודת הרינדור במהלך טעינת הדף ואת עבודת הרינדור בתגובה לאינטראקציות של משתמשים היא להסתמך על מאפיין ה-CSS content-visibility
, שבעצם מאפשר לבצע רינדור עצלני של רכיבים כשהם מתקרבים לאזור התצוגה. יכול להיות שיידרש תרגול כדי להשתמש ב-content-visibility
בצורה יעילה, אבל כדאי לבדוק אם השימוש בו יקצר את זמן הרינדור וישפר את מדד ה-INP של הדף.
חשוב לשים לב לעלויות הביצועים כשמעבדים HTML באמצעות JavaScript
בכל מקום שיש בו HTML, יש בו ניתוח HTML, ואחרי שהדפדפן מסיים לנתח HTML ל-DOM, הוא צריך להחיל עליו סגנונות, לבצע חישובי פריסה ואז לעבד את הפריסה הזו. זו עלות שאי אפשר להימנע ממנה, אבל האופן שבו מתבצע רינדור של HTML משפיע על העלות.
כשהשרת שולח HTML, הוא מגיע לדפדפן כזרם. סטרימינג פירושו שתגובת ה-HTML מהשרת מגיעה בחלקים. הדפדפן מבצע אופטימיזציה של אופן הטיפול בזרם על ידי ניתוח מצטבר של חלקי הזרם כשהם מגיעים, והצגתם חלק אחר חלק. זוהי אופטימיזציה של הביצועים, כי הדפדפן מוותר באופן מרומז על השליטה מעת לעת ובאופן אוטומטי במהלך טעינת הדף, ואתם מקבלים את זה בחינם.
הביקור הראשון בכל אתר תמיד יכלול כמות מסוימת של HTML, אבל גישה נפוצה היא להתחיל עם קטע מינימלי של HTML, ואז להשתמש ב-JavaScript כדי לאכלס את אזור התוכן. עדכונים עתידיים באזור התוכן הזה מתרחשים גם כתוצאה מאינטראקציות של משתמשים. השיטה הזו נקראת בדרך כלל מודל של אפליקציה בדף יחיד (SPA). חיסרון אחד של התבנית הזו הוא שכשמפעילים HTML באמצעות JavaScript בצד הלקוח, לא רק שמשלמים על העיבוד של JavaScript כדי ליצור את ה-HTML, אלא גם הדפדפן לא יניב עד שהוא יסיים לנתח את ה-HTML ולהפעיל אותו.
עם זאת, חשוב לזכור שגם אתרים שלא מבוססים על SPA כנראה יכללו כמות מסוימת של עיבוד HTML באמצעות JavaScript כתוצאה מאינטראקציות. בדרך כלל זה בסדר, כל עוד אתם לא מעבדים כמויות גדולות של HTML בצד הלקוח, כי זה עלול לעכב את הצגת הפריים הבא. עם זאת, חשוב להבין את ההשלכות של הגישה הזו על הביצועים של עיבוד HTML בדפדפן, ואיך היא יכולה להשפיע על הרספונסיביות של האתר לקלט של המשתמשים אם מעבדים הרבה HTML באמצעות JavaScript.
סיכום
שיפור ה-INP של האתר הוא תהליך שצריך לבצע כל כמה זמן. כשמתקנים אינטראקציה איטית בשטח, יש סיכוי טוב – במיוחד אם באתר יש הרבה אינטראקטיביות – שתתחילו לזהות אינטראקציות איטיות אחרות, ותצטרכו לבצע גם להן אופטימיזציה.
הדרך לשפר את מדד INP היא התמדה. עם הזמן, תוכלו לשפר את הרספונסיביות של הדף כך שהמשתמשים יהיו מרוצים מהחוויה שאתם מספקים להם. בנוסף, סביר להניח שכשתפתחו תכונות חדשות למשתמשים, תצטרכו לעבור את אותו תהליך כדי לבצע אופטימיזציה של אינטראקציות שספציפיות להם. זה ייקח זמן ומאמץ, אבל זה שווה את זה.
תמונה ראשית (Hero) מ-Unsplash, מאת David Pisnoy. התמונה שונתה בהתאם לרישיון Unsplash.