הקלט מגיע למצב Compositor
זהו האחרון בסדרת בלוגים בת 4 חלקים שבה בוחנים את Chrome. לבדוק איך הוא מטפל בקוד שלנו להצגת אתר. בפוסט הקודם, בדקנו את תהליך העיבוד ולמדנו על המרכיב. בפוסט הזה לבחון איך קומפוזיציה מאפשר אינטראקציה חלקה כאשר קלט משתמש מגיע.
הזנת אירועים מנקודת המבט של הדפדפן
כשתשמעו את ההודעה "אירועי קלט" תחשבו רק על הקלדה בתיבת טקסט או בלחיצת עכבר, מנקודת המבט של הדפדפן, 'קלט' פירושו כל תנועה מהמשתמש. גלילה באמצעות גלגל העכבר היא קלט גם אירוע קלט וגם נגיעה או עכבר או העברת העכבר מעליו.
כאשר מתבצעת תנועת משתמש כמו נגיעה במסך, תהליך הדפדפן הוא זה שמקבל את
בתור התחלה. עם זאת, תהליך הדפדפן מודע רק למקום שבו התנועה התרחשה מאז
תוכן שנמצא בתוך כרטיסייה מטופל על ידי תהליך הרינדור. התהליך בדפדפן שולח את האירוע,
סוג (למשל touchstart
) והקואורדינטות שלו לתהליך כלי הרינדור. תהליך הרינדור מטפל
את האירוע המתאים באמצעות מציאת יעד האירוע והפעלת פונקציות event listener המצורפים.
![אירוע של קלט](https://developer.chrome.com/static/blog/inside-browser-part4/image/input-event-265a73164e715.png?authuser=9&hl=he)
המרכיב מקבל אירועי קלט
בפוסט הקודם, בדקנו איך המרכיב יכול להתמודד עם גלילה חלקה על ידי הרכבה בשכבות רסטריזציה. אם לא מצורפים לדף פונקציות event listener ליצור מסגרת מורכבת חדשה שלא תלויה לחלוטין ב-thread הראשי. אבל מה קורה אם אירוע מסוים מאזינים צורפו לדף? איך השרשור של המחבר יבין אם יש צורך באירוע לטיפול?
הסבר על אזורים שאינם ניתנים לגלילה מהירה
מכיוון שהרצת JavaScript היא המשימה של ה-thread הראשי, כשיש דף מורכב, ה-thread של המרכיב מסמן אזור בדף שבו מצורפים גורמים מטפלים באירועים כ'אזור שלא ניתן לגלילה מהירה'. על ידי עם המידע הזה, ה-thread של המרכיב יכול לוודא לשלוח את אירוע הקלט ל-thread הראשי אם האירוע מתרחש באזור הזה. אם אירוע הקלט מגיע מחוץ לאזור הזה, הערך של ה-thread של הקומפוזיציה ממשיך להרכיב פריים חדש בלי לחכות ל-thread הראשי.
![אזור מוגבל שלא ניתן לגלול במהירות](https://developer.chrome.com/static/blog/inside-browser-part4/image/limited-non-fast-scrollab-376be5ee2cd6b.png?authuser=9&hl=he)
חשוב לשים לב כשכותבים גורמים מטפלים באירועים.
דפוס נפוץ של טיפול באירועים בפיתוח אתרים הוא הענקת גישה לאירועים. מכיוון שהאירועים מוצגים בבועות, יכול לצרף מטפל אחד לאירועים ברכיב העליון ביותר ולהקצות משימות על סמך יעד האירוע. שלך רואה או כתב קוד כמו בדוגמה שבהמשך.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
צריך לכתוב רק הגורם המטפל באירועים אחד לכל הרכיבים, לכן הארגונומית של האירוע דפוס הענקת הגישה אטרקטיבי. עם זאת, אם תסתכלו על הקוד הזה מנקודת המבט של הדפדפן, בתצוגה, עכשיו כל הדף מסומן כאזור שלא ניתן לגלילה מהירה. כלומר, גם אם ליישום לא חשובות לקלט מחלקים מסוימים של הדף, ה-thread של המרכיב צריך לתקשר עם ה-thread הראשי ולהמתין לו בכל פעם שמגיע אירוע קלט. לכן, יכולת הגלילה החלקה של המרכיב מתבטלת.
![אזור של דף מלא שלא ניתן לגלול במהירות](https://developer.chrome.com/static/blog/inside-browser-part4/image/full-page-non-fast-scroll-dd3010cc3ee0f.png?authuser=9&hl=he)
כדי לצמצם את הסיכון, אפשר להעביר את האפשרויות של passive: true
באירוע
Listener. כך תרמז לדפדפן שאתם עדיין רוצים להאזין לאירוע בשרשור הראשי.
אבל compositor יכול להמשיך ליצור גם פריים חדש מורכב.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
איך בודקים אם אפשר לבטל את האירוע
![גלילה בדף](https://developer.chrome.com/static/blog/inside-browser-part4/image/page-scroll-2cf8d804f8587.png?authuser=9&hl=he)
נניח שיש בדף תיבה שבה אתם רוצים להגביל את כיוון הגלילה לגלילה אופקית בלבד.
שימוש באפשרות passive: true
באירוע הסמן משמעותו שהגלילה בדף יכולה להיות חלקה, אבל
כדי להגביל את מספר הגלילה האנכית, יכול להיות שהגלילה האנכית תתחיל עד השעה שבה את רוצה preventDefault
כיוון הגלילה. אפשר לבדוק את זה באמצעות השיטה event.cancelable
.
document.body.addEventListener('pointermove', event => {
if (event.cancelable) {
event.preventDefault(); // block the native scroll
/*
* do what you want the application to do here
*/
}
}, {passive: true});
לחלופין, אפשר להשתמש בכלל CSS כמו touch-action
כדי להסיר לחלוטין את הגורם המטפל באירועים.
#area {
touch-action: pan-x;
}
איך לאתר את יעד האירוע
![בדיקת הצלחה](https://developer.chrome.com/static/blog/inside-browser-part4/image/hit-test-39f1d20855064.png?authuser=9&hl=he)
כשה-thread של הקומפוזיטור שולח אירוע קלט ל-thread הראשי, הדבר הראשון לרוץ הוא היט בבדיקה כדי למצוא את יעד האירוע. בבדיקת היטים נעשה שימוש בנתונים של רשומות צבע שנוצרו ברינדור כדי להבין מה נמצא מתחת לקואורדינטות של הנקודות שבהן האירוע התרחש.
צמצום מספר שליחת האירועים ל-thread הראשי
בפוסט הקודם, הסברנו איך התצוגה הטיפוסית שלנו מרעננת את המסך 60 פעמים בשנייה איך אנחנו צריכים לעמוד בקצב של אנימציה חלקה. כדי להזין את הקלט, מסך מגע רגיל מכשיר מספק אירוע מגע 60-120 פעמים בשנייה, ועכבר טיפוסי מבצע אירועים 100 פעמים שנייה. רמת הדיוק של אירוע הקלט גבוהה יותר מזו שהמסך שלנו יכול לרענן.
אם אירוע רציף כמו touchmove
נשלח ל-thread הראשי 120 פעמים בשנייה,
עלול להפעיל כמות מופרזת של בדיקות התאמה וביצוע JavaScript, בהשוואה למידת האיטיות
ניתן לרענן את המסך.
![אירועים ללא סינון](https://developer.chrome.com/static/blog/inside-browser-part4/image/unfiltered-events-5c569da8f6466.png?authuser=9&hl=he)
כדי לצמצם קריאות מיותרות ל-thread הראשי, Chrome מקבץ אירועים רציפים (כמו
wheel
, mousewheel
, mousemove
, pointermove
, touchmove
) ועיכובים במשלוחים עד
ממש לפני requestAnimationFrame
הבא.
![אירועים מאוחדים](https://developer.chrome.com/static/blog/inside-browser-part4/image/coalesced-events-42fbb3813612d.png?authuser=9&hl=he)
אירועים נפרדים כמו keydown
, keyup
, mouseup
, mousedown
, touchstart
ו-touchend
נשלחים באופן מיידי.
שימוש ב-getCoalescedEvents
כדי לקבל אירועים בתוך הפריים
ברוב אפליקציות האינטרנט, אירועים מאוחדים אמורים להספיק כדי לספק חוויית משתמש טובה.
עם זאת, אם אתם מפתחים דברים כמו שרטוט של אפליקציה והצבת נתיב
touchmove
קואורדינטות, ייתכן שתאבדו בין קואורדינטות כדי לשרטט קו חלק. במקרה הזה,
אפשר להשתמש בשיטה getCoalescedEvents
באירוע של מיקום הסמן כדי לקבל מידע עליהם
אירועים מאוחדים.
![getCoalescedEvents](https://developer.chrome.com/static/blog/inside-browser-part4/image/getcoalescedevents-ab59c1cb92e1b.png?authuser=9&hl=he)
window.addEventListener('pointermove', event => {
const events = event.getCoalescedEvents();
for (let event of events) {
const x = event.pageX;
const y = event.pageY;
// draw a line using x and y coordinates.
}
});
השלבים הבאים
בסדרה הזו עסקנו בתפעול הפנימי של דפדפן אינטרנט. אם מעולם לא חשבתם למה
ההמלצה של כלי הפיתוח היא להוסיף את {passive: true}
לגורם שמטפל באירועים, או להסביר למה כדאי לכתוב async
בתג הסקריפט שלך, אני מקווה שהסדרה הזו הצליחה להסביר למה דפדפן צריך
כדי לספק חוויית אינטרנט מהירה וחלקה יותר.
שימוש ב-Lighthouse
אם אתם רוצים שהקוד יהיה נחמד לדפדפן אבל אתם לא יודעים מאיפה להתחיל, Lighthouse הוא כלי שבעזרתו אפשר לבדוק אתרים לדווח מה עושים כמו שצריך ומה שצריך לשפר. קריאה של רשימת הביקורות אפשר גם להבין מהם הדברים שחשובים לדפדפן.
איך מודדים ביצועים
שינויים בביצועים עשויים להשתנות באתרים שונים, ולכן חשוב מאוד למדוד את הביצועים של האתר שלכם, ולהחליט מה הכי מתאים לאתר. צוות כלי הפיתוח ל-Chrome מציע כמה מדריכים בנושא איך למדוד את ביצועי האתר.
הוספת מדיניות של תכונות לאתר
אם ברצונך לעשות צעד נוסף, מדיניות התכונות היא מדיניות חדשה
תכונה של פלטפורמת אינטרנט שיכולה לשמש אתכם כשכבת הגנה בזמן בניית הפרויקט. מתבצעת הפעלה
המדיניות בנושא תכונות מבטיחה התנהגות מסוימת של האפליקציה ומונעת טעויות.
לדוגמה, אם אתם רוצים לוודא שהאפליקציה אף פעם לא תחסום את הניתוח, אתם יכולים להריץ את האפליקציה על
המדיניות בנושא סקריפטים סינכרוניים. כש-sync-script: 'none'
מופעל, JavaScript שחוסם את הניתוח יגרום
לא ניתן יהיה להפעיל אותו. הפעולה הזו מונעת מהקוד לחסום את המנתח,
הדפדפן לא צריך לדאוג לגבי השהיית המנתח.
סיכום
![תודה](https://developer.chrome.com/static/blog/inside-browser-part4/image/thank-you-cae9a20f3c237.png?authuser=9&hl=he)
כשהתחלתי לבנות אתרים, כמעט רציתי לכתוב את הקוד שלי תעזור לי לשפר את הפרודוקטיביות. הדברים האלה חשובים, אבל צריך לחשוב גם איך לוקח את הקוד שאנחנו כותבים. דפדפנים מודרניים כבר משקיעים בדרכים הבאות: מספקות למשתמשים חוויית אינטרנט טובה יותר. להיות נחמדים לדפדפן באמצעות ארגון הקוד שלנו, בתורו, משפר את חוויית המשתמש שלך. אני מקווה שתצטרפו אליי בקווסט כדי להיות נחמדים לדפדפנים.
תודה רבה לכל מי שבחן את הטיוטות המוקדמות של הסדרה, כולל (בין היתר) to): אלכס ראסל, פול אירלנד, מגן קירני, אריק ביילמן, מתיאס ביינס, Addy Osmani, קינוקו יאסודה, נאסקו אוסקוב, וגם צ'רלי רייס.
נהנית מהסדרה הזו? אם יש לך שאלות או הצעות לפוסט עתידי, אשמח לשמוע ממך בקטע התגובות בהמשך או ב-@kosamari בטוויטר.