מה קורה בניווט
זה החלק השני מתוך סדרת בלוגים בת 4 חלקים שמציגה את התכונות הפנימיות של Chrome. בפוסט הקודם הסברנו איך תהליכים ושרשורים שונים מטפלים בחלקים שונים של הדפדפן. בפוסט הזה נסביר בפירוט איך כל תהליך ושרשור מתקשרים כדי להציג אתר.
נבחן מקרה שימוש פשוט של גלישה באינטרנט: אתם מקלידים כתובת אתר בדפדפן, ולאחר מכן הדפדפן מאחזר נתונים מהאינטרנט ומציג דף. בפוסט הזה נתמקד בחלק שבו המשתמש מבקש אתר, והדפדפן מתכונן לעבד דף – שנקרא גם ניווט.
הוא מתחיל בתהליך בדפדפן
כפי שהסברנו בחלק 1: מעבד (CPU), GPU, זיכרון וארכיטקטורה מרובת תהליכים, כל מה שמחוץ לכרטיסייה מטופל בתהליך הדפדפן. בתהליך הדפדפן יש שרשורים כמו ה-thread של ממשק המשתמש, שמושך לחצנים ושדות קלט של הדפדפן, ה-thread של הרשת שעוסק בסטאק הרשת לקבלת נתונים מהאינטרנט, שרשור האחסון ששולט בגישה לקבצים ועוד. כשמקלידים כתובת URL בסרגל הכתובות, הקלט עובר עיבוד בשרשור ממשק המשתמש של תהליך הדפדפן.
ניווט פשוט
שלב 1: טיפול בקלט
כשמשתמש מתחיל להקליד בסרגל הכתובות, הדבר הראשון שמסומן בשרשור של ממשק המשתמש הוא "האם זו שאילתת חיפוש או כתובת URL?". ב-Chrome, גם סרגל הכתובות הוא שדה להזנת קלט בחיפוש, לכן צריך לנתח את שרשור ממשק המשתמש ולהחליט אם לשלוח אותו למנוע חיפוש או לאתר שביקשת.
שלב 2: מתחילים בניווט
כשמשתמש לוחץ על Enter, השרשור בממשק המשתמש מפעיל קריאת רשת כדי לקבל את תוכן האתר. סימן גרפי של טעינה מוצג בפינת הכרטיסייה, ושרשור הרשת עובר פרוטוקולים מתאימים כמו חיפוש DNS ויצירת חיבור TLS (אבטחת שכבת התעבורה) עבור הבקשה.
בשלב הזה, שרשור הרשת עשוי לקבל כותרת הפניה לשרת כמו HTTP 301. במקרה כזה, שרשור הרשת מתקשר עם שרשור ממשק המשתמש שהשרת מבקש הפניה אוטומטית. לאחר מכן, תופעל בקשה נוספת לכתובת URL.
שלב 3: קריאת התשובה
אחרי שגוף התגובה (payload) מתחיל להיכנס, שרשור הרשת בודק את הבייטים הראשונים של השידור, לפי הצורך. כותרת Content-Type של התגובה אמורה לציין את סוג הנתונים, אך מכיוון שייתכן שהיא חסרה או שגויה, כאן מתבצע סריקה של סוג MIME. זהו 'עסק מסובך', כפי שצוין בקוד המקור. אפשר לקרוא את התגובה כדי לראות איך דפדפנים שונים מטפלים בצמדים של סוג תוכן/מטען ייעודי (payload).
אם התשובה היא קובץ HTML, בשלב הבא צריך להעביר את הנתונים לתהליך הרינדור, אבל אם מדובר בקובץ ZIP או בקובץ אחר, מדובר בבקשת הורדה ולכן הם יצטרכו להעביר את הנתונים למנהל ההורדות.
כאן גם מתבצעת בדיקת SafeBrowsing. אם נראה שהדומיין ונתוני התגובה תואמים לאתר זדוני ידוע, יוצג דף אזהרה בשרשור הרשת. בנוסף, מתבצעת בדיקה של Cחסימה CC (C) כדי לוודא שנתונים רגישים מאתרים שונים לא מגיעים לתהליך הרינדור.
שלב 4: מוצאים תהליך של כלי רינדור
כשכל הבדיקות מסתיימות ו-Networkthread בטוח שהדפדפן צריך לנווט לאתר המבוקש, השרשור של Network מורה ל-thread של ממשק המשתמש שהנתונים מוכנים. לאחר מכן, ה-UI thread מוצא תהליך רינדור כדי להמשיך את הרינדור של דף האינטרנט.
מכיוון שהתגובה לבקשה מהרשת יכולה להימשך כמה מאות אלפיות השנייה, מיושמת אופטימיזציה לזירוז התהליך. כששרשור ממשק המשתמש שולח בקשה לכתובת URL לשרשור הרשת בשלב 2, המערכת כבר יודעת לאיזה אתר המשתמשים מנווטים. המטרה של ה-UI ב-thread היא למצוא או להתחיל באופן יזום תהליך של רינדור במקביל לבקשת הרשת. כך, אם הכול יפעל כצפוי, תהליך של רינדור כבר נמצא במצב המתנה בזמן קבלת נתונים ב-thread של הרשת. ייתכן שלא ניתן יהיה להשתמש בתהליך ההמתנה אם הניווט מפנה אוטומטית בין אתרים, ובמקרה כזה ייתכן שיהיה צורך בתהליך אחר.
שלב 5: מבצעים ניווט
עכשיו, אחרי שהנתונים ותהליך הרינדור מוכנים, כתובת IPC נשלחת מתהליך הדפדפן לתהליך הרינדור כדי לבצע את הניווט. היא גם מעבירה את מקור הנתונים, כך שתהליך הרינדור יכול להמשיך לקבל נתוני HTML. אחרי שמתקבל אישור על כך שתהליך הדפדפן התבצעה בתהליך הרינדור, הניווט הושלם ושלב טעינת המסמך מתחיל.
בשלב הזה סרגל הכתובות מתעדכן ואינדיקטור האבטחה וממשק המשתמש של הגדרות האתר משקפים את פרטי האתר של הדף החדש. היסטוריית הסשנים של הכרטיסייה תעודכן כך שלחצני 'הקודם'/'הבא' יעבירו את המשתמשים לאתר שאליו בדיוק ניווטתם. כדי שיהיה קל לשחזר כרטיסייה או סשן כשסוגרים כרטיסייה או חלון, היסטוריית הסשנים נשמרת בדיסק.
שלב נוסף: הטעינה הראשונית הושלמה
לאחר התחייבות לניווט, תהליך הרינדור מכיל טעינה של משאבים ומעבד את הדף. אנו נעבור על הפרטים של מה שקורה בשלב זה בפוסט הבא. אחרי שהכלי לעיבוד "מסיים" את העיבוד, הוא שולח IPC חזרה לתהליך הדפדפן (כלומר, אחרי כל האירועים של onload
הופעלו בכל המסגרות בדף וסיימו את ביצועם). בשלב הזה,
ה-thread של ממשק המשתמש עוצר את סימן ההרצה של הטעינה בכרטיסייה.
אני אומר "סיום", מכיוון ש-JavaScript בצד הלקוח עדיין יכול לטעון משאבים נוספים ולהציג תצוגות חדשות לאחר נקודה זו.
ניווט לאתר אחר
הניווט הפשוט הושלם! אבל מה קורה אם משתמש מוסיף שוב כתובת URL שונה לסרגל הכתובות? ובכן, תהליך הדפדפן מבצע אותם שלבים כדי לנווט לאתר השונה.
עם זאת, לפני שאפשר יהיה לעשות זאת, הם צריכים לבדוק באתר שעבר עיבוד אם חשוב להם אירוע
beforeunload
.
ל-beforeunload
יש אפשרות ליצור את ההתראה 'לצאת מהאתר הזה?' כשמנסים לנווט אל מחוץ לכרטיסייה או לסגור אותה.
כל מה שנמצא בתוך הכרטיסייה, כולל קוד ה-JavaScript, מטופל בתהליך הרינדור, לכן
תהליך הדפדפן צריך לבדוק את תהליך הרינדור הנוכחי כשמתקבלת בקשת ניווט חדשה.
אם הניווט הופעל מתהליך הרינדור (למשל, משתמש לחץ על קישור או
שה-JavaScript בצד הלקוח הפעיל window.location = "https://newsite.com"
), תהליך הרינדור יבדוק קודם את רכיבי ה-handler של beforeunload
. לאחר מכן הוא עובר את אותו תהליך כמו תהליך הניווט ביוזמת הדפדפן. ההבדל היחיד הוא שבקשת הניווט מתחילה משלב הרינדור ועד לתהליך הדפדפן.
כשהניווט החדש נשלח לאתר אחר מזה שעבר עיבוד כרגע, מופעל תהליך עיבוד נפרד כדי לטפל בניווט החדש, בעוד שתהליך העיבוד הנוכחי נשמר כדי
לטפל באירועים כמו unload
. למידע נוסף, קראו את הסקירה הכללית על מצבי מחזור החיים של הדף ועל האופן שבו אתם יכולים להתחבר לאירועים בעזרת ה-API של מחזור החיים של הדף.
במקרה של Service Worker
אחד מהשינויים שנערכו לאחרונה בתהליך הניווט הזה היה הוספת Service Worker. קובץ שירות (service worker) הוא דרך לכתוב שרת proxy של רשת בקוד האפליקציה, והוא מאפשר למפתחי אתרים לשלוט טוב יותר על הקבצים שנשמרים במטמון באופן מקומי ומתי הם מקבלים נתונים חדשים מהרשת. אם קובץ השירות מוגדר לטעון את הדף מהמטמון, אין צורך לבקש את הנתונים מהרשת.
מה שחשוב לזכור הוא שה-Service Worker הוא קוד JavaScript שפועל בתהליך רינדור. אבל כשבקשת הניווט נכנסת, איך תהליך דפדפן יודע לאתר יש קובץ שירות (service worker)?
כאשר קובץ שירות (service worker) רשום, ההיקף של קובץ השירות נשמר בתור הפניה (מידע נוסף על ההיקף זמין במאמר מחזור החיים של Service Worker). במהלך ניווט, שרשור רשת בודק את הדומיין ביחס להיקפים של קובצי שירות (service worker) רשומים. אם רשום עבור כתובת ה-URL הזו קובץ שירות (service worker), ה-UI thread מוצא תהליך רינדור כדי להפעיל את הקוד של Service Worker. ה-Service Worker עשוי לטעון נתונים מהמטמון, וכך למנוע את הצורך לבקש נתונים מהרשת או לבקש משאבים חדשים מהרשת.
טעינה מראש של ניווט
מעבר בין תהליך הדפדפן לתהליך הרינדור עלול לגרום לעיכובים, אם קובץ השירות (service worker) מחליט בסופו של דבר לבקש נתונים מהרשת. טעינה מראש של ניווט היא מנגנון לזירוז התהליך הזה על ידי טעינת משאבים במקביל להפעלה של Service Worker. היא מסמנת את הבקשות האלה עם כותרת, ומאפשרת לשרתים להחליט אם לשלוח תוכן שונה לבקשות האלה. לדוגמה, רק נתונים מעודכנים במקום מסמך מלא.
סיכום
בפוסט הזה בדקנו מה קורה במהלך הניווט, והסברנו איך הקוד של אפליקציית האינטרנט, כמו כותרות התגובות ו-JavaScript בצד הלקוח, משתלבים עם הדפדפן. אם תדעו אילו שלבים הדפדפן עובר כדי לקבל נתונים מהרשת, תוכלו להבין בקלות למה פותחו ממשקי API, כמו טעינה מראש של ניווט. בפוסט הבא נפרט איך הדפדפן מעריך את HTML/CSS/JavaScript כדי לעבד דפים.
נהנית מהפוסט? אם יש לכם שאלות או הצעות לפוסט הבא, אשמח לשמוע מכם בקטע התגובות בהמשך או @kosamari ב-Twitter.