מבט מבפנים על דפדפן אינטרנט מודרני (חלק 2)

Mariko Kosaka

מה קורה במהלך הניווט

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

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

הוא מתחיל בתהליך בדפדפן

תהליכים בדפדפן
איור 1: ממשק המשתמש של הדפדפן בחלק העליון, תרשים של תהליך הדפדפן עם שרשור של ממשק המשתמש, הרשת והאחסון בחלק התחתון

כפי שציינו בחלק 1: מעבד (CPU), מעבד גרפי (GPU), זיכרון וארכיטקטורה של תהליכים מרובים, כל מה שמחוץ לכרטיסייה מטופל על ידי תהליך הדפדפן. לתהליך הדפדפן יש מספר שרשראות, כמו שרשרת ממשק המשתמש שמשרטטת את הלחצנים ואת שדות הקלט של הדפדפן, שרשרת הרשת שמטפלת ב-stack הרשת כדי לקבל נתונים מהאינטרנט, שרשרת האחסון ששולטת בגישה לקבצים ועוד. כשמקלידים כתובת URL בסרגל הכתובות, הקלט מטופל על ידי שרשור ממשק המשתמש של תהליך הדפדפן.

ניווט פשוט

שלב 1: טיפול בקלט

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

טיפול בקלט של משתמשים
איור 1: שרשור בממשק המשתמש עם שאלה אם הקלט הוא שאילתה לחיפוש או כתובת URL

שלב 2: מתחילים בניווט

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

התחלת הניווט
איור 2: שרשור ממשק המשתמש פונה לשרשור הרשת כדי לנווט אל mysite.com

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

שלב 3: קוראים את התשובה

תגובת HTTP
איור 3: כותרת התגובה שמכילה את Content-Type ואת המטען הייעודי (Payload) שהוא הנתונים בפועל

כשגוף התגובה (מטען שימושי) מתחיל להגיע, אם צריך, חוט הרשת בודק את הבייטים הראשונים של הסטרימינג. בכותרת Content-Type של התגובה צריך להופיע סוג הנתונים, אבל יכול להיות שהיא תהיה חסרה או שגויה, ולכן מתבצעת כאן ניפוי של סוג ה-MIME. זוהי 'בעיה מורכבת', כפי שצוין בקוד המקור. אפשר לקרוא את התגובה כדי לראות איך דפדפנים שונים מתייחסים לזוגות של סוג תוכן/מטען שימושי.

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

זיהוי סוג MIME
איור 4: שרשור ברשת עם שאלה אם נתוני התגובה הם HTML מאתר בטוח

כאן מתבצעת גם בדיקת SafeBrowsing. אם הדומיין ונתוני התגובה נראים תואמים לאתר זדוני ידוע, השרשור ברשת מתריע על כך ומציג דף אזהרה. בנוסף, מתבצעת בדיקה של Cross Origin Read Blocking (CORB) כדי לוודא שנתונים רגישים באתרים שונים לא מגיעים לתהליך העיבוד.

שלב 4: חיפוש תהליך של עיבוד גרפיקה

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

חיפוש תהליך הניתוח
איור 5: שרשור רשת שמורה לשרשור ממשק המשתמש למצוא את תהליך ה-Renderer

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

שלב 5: ביצוע השינויים בתפריט הניווט

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

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

ביצוע השינויים בניווט
איור 6: IPC בין הדפדפן לבין תהליכי ה-renderer, בקשה לעיבוד הדף

שלב נוסף: הטעינה הראשונית הושלמה

אחרי שהניווט מחויב, תהליך העיבוד ממשיך לטעון משאבים ולעבד את הדף. בפוסט הבא נסביר מה קורה בשלב הזה. אחרי שתהליך ה-renderer 'מסיים' את העיבוד, הוא שולח הודעה של IPC בחזרה לתהליך הדפדפן (זה קורה אחרי שכל אירועי onload מופעלים בכל המסגרות בדף וסיימו את הביצוע). בשלב הזה, שרשור ממשק המשתמש מפסיק את סימן הטעינה בכרטיסייה.

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

סיום הטעינה של הדף
איור 7: IPC מהמתמר לעיבוד נתונים לתהליך הדפדפן כדי להודיע שהדף 'נטען'

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

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

גורם מטפל באירוע beforeunload
איור 8: IPC מתהליך הדפדפן לתהליך עיבוד הנתונים, שמציין שהוא עומד לנווט לאתר אחר

אם הניווט הופעל מתהליך ה-renderer (למשל, המשתמש לחץ על קישור או ש-JavaScript בצד הלקוח הפעיל את window.location = "https://newsite.com"), תהליך ה-renderer בודק קודם את הטיפולים של beforeunload. לאחר מכן, הוא עובר את אותו תהליך כמו ניווט שהופעל על ידי תהליך בדפדפן. ההבדל היחיד הוא שבקשת הניווט מופעלת מתהליך ה-renderer לתהליך הדפדפן.

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

ניווט ופריקה חדשים
איור 9: 2 הודעות IPC מתהליך הדפדפן לתהליך עיבוד חדש, שמבקשות לעבד את הדף ולפרוק את תהליך העיבוד הישן

במקרה של Service Worker

אחד השינויים האחרונים בתהליך הניווט הזה הוא ההשקה של service worker. קובץ שירות (service worker) הוא דרך לכתוב שרת proxy ברשת בקוד האפליקציה. כך למפתחי האינטרנט יש יותר שליטה על מה ששמור במטמון באופן מקומי ומתי לקבל נתונים חדשים מהרשת. אם ה-service worker מוגדר לטעון את הדף מהמטמון, אין צורך לבקש את הנתונים מהרשת.

חשוב לזכור ש-service worker הוא קוד JavaScript שפועל בתהליך רינדור. אבל כשמגיעה בקשת הניווט, איך תהליך בתוך הדפדפן יודע שלאתר יש שירות עובד?

חיפוש ברמת קובץ השירות (service worker)
איור 10: שרשור הרשת בתהליך הדפדפן שמחפש את היקף השירות של ה-service worker

כשרושמים עובד שירות, ההיקף שלו נשמר כמידע עזר (מידע נוסף על ההיקף זמין במאמר מחזור החיים של עובד השירות). כשמתרחשת ניווט, חוט הרשת בודק את הדומיין מול היקפי השירות הרשומים של ה-service worker. אם ה-service worker רשום לכתובת ה-URL הזו, חוט ממשק המשתמש מוצא תהליך עיבוד כדי להריץ את הקוד של ה-service worker. ה-service worker עשוי לטעון נתונים מהמטמון, וכך למנוע את הצורך לבקש נתונים מהרשת, או לבקש משאבים חדשים מהרשת.

ניווט ב-serviceworker
איור 11: חוט ממשק המשתמש בתהליך הדפדפן מפעיל תהליך עיבוד תמונות כדי לטפל בעובדים של השירות. לאחר מכן, חוט עבודה בתהליך עיבוד התמונות מבקש נתונים מהרשת

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

טעינה מראש של נתוני ניווט
איור 12: חוט ממשק המשתמש בתהליך דפדפן שמפעיל תהליך עיבוד גרפיקה כדי לטפל בעובד השירות, תוך כדי הפעלת בקשת רשת במקביל

סיכום

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

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

השלב הבא: האופן שבו פועל תהליך עיבוד