מה קורה בניווט
זהו החלק השני מתוך סדרת בלוגים בת 4 חלקים שבה בוחנים את היכולות הפנימיות של Chrome. בפוסט הקודם בדקנו את ההבדלים תהליכים ושרשורים מטפלים בחלקים שונים של הדפדפן. בפוסט הזה אנחנו מעמיקים איך כל תהליך ושרשור מתקשרים כדי להציג אתר.
נבחן תרחיש פשוט לדוגמה של גלישה באינטרנט: מקלידים את כתובת ה-URL בדפדפן, ולאחר מכן בדפדפן שולפת נתונים מהאינטרנט ומציגה דף. בפוסט הזה נתמקד בחלק שבו משתמש מבקש אתר והדפדפן מתכונן לעבד דף - שנקרא גם ניווט.
הוא מתחיל בתהליך בדפדפן
![תהליכי דפדפן](https://developer.chrome.com/static/blog/inside-browser-part2/image/browser-processes-1abcf214c73ef.png?authuser=5&hl=he)
כמו שהסברנו בסרטון חלק 1: מעבד (CPU), GPU, זיכרון וארכיטקטורה מרובת תהליכים, כל מה שנמצא מחוץ לכרטיסייה מטופל על ידי תהליך הדפדפן. תהליך הדפדפן כולל שרשורים כמו ה-thread של ממשק המשתמש, שמשרטטים לחצנים ושדות קלט של הדפדפן, שרשור הרשת שעוסק בסטאק רשת לקבלת נתונים מהאינטרנט, את שרשור האחסון ששולט בגישה לקבצים ועוד. כשמקלידים כתובת URL בכתובת הקלט שלך מטופל על ידי ה-thread של ממשק המשתמש בדפדפן.
ניווט פשוט
שלב 1: טיפול בקלט
כשמשתמש מתחיל להקליד בסרגל הכתובות, השאלה הראשונה ב-UI בממשק המשתמש היא "האם זה שאילתת חיפוש או כתובת URL?". ב-Chrome, גם סרגל הכתובות הוא שדה להזנת קלט לחיפוש, ולכן השרשור בממשק המשתמש צריך לנתח את החשבון ולהחליט אם לשלוח אתכם למנוע חיפוש או לאתר שביקשתם.
![טיפול בקלט של משתמשים](https://developer.chrome.com/static/blog/inside-browser-part2/image/handling-user-input-24fea2c817a6a.png?authuser=5&hl=he)
שלב 2: מתחילים בניווט
כשמשתמש לוחץ על Enter, השרשור בממשק המשתמש מתחיל שיחת רשת כדי לקבל את תוכן האתר. סימן גרפי שמוצג בזמן טעינה מוצג בפינה של כרטיסייה, ושרשור הרשת עובר דרך פרוטוקולים מתאימים כמו חיפוש DNS וחיבור TLS לבקשה.
![התחלת ניווט](https://developer.chrome.com/static/blog/inside-browser-part2/image/navigation-start-4aeb163d61a8c.png?authuser=5&hl=he)
בשלב הזה, שרשור הרשת עשוי לקבל כותרת הפניה אוטומטית של השרת, כמו HTTP 301. במקרה הזה, ה-thread של הרשת מתקשר עם ה-thread של ממשק המשתמש שהשרת מבקש הפניה אוטומטית. לאחר מכן: תישלח בקשה נוספת לכתובת URL.
שלב 3: קריאת התשובה
![תגובת HTTP](https://developer.chrome.com/static/blog/inside-browser-part2/image/http-response-0ae2751b24973.png?authuser=5&hl=he)
אחרי שגוף התשובה (המטען הייעודי (Payload) מתחיל להגיע, ה-thread של הרשת בודק את הבייטים הראשונים של הסטרימינג, אם יש צורך. כותרת Content-Type של התגובה צריכה לציין מהו סוג הנתונים, אבל מכיוון שהוא עשוי להיות חסר או שגוי, לכידת סוגי MIME מתבצעת כאן. "עסק בעייתי" כפי שמצוין בקוד המקור. תוכלו לקרוא את התגובה כדי לראות איך דפדפנים שונים מטפלים בצמדים של סוג תוכן/מטען ייעודי (payload).
אם התגובה היא קובץ HTML, השלב הבא יהיה העברת הנתונים למעבד אבל אם מדובר בקובץ ZIP או בקובץ אחר, המשמעות היא שזו בקשת הורדה הוא צריך להעביר את הנתונים למנהל ההורדות.
![לכידת סוג MIME](https://developer.chrome.com/static/blog/inside-browser-part2/image/mime-type-sniffing-444e1a2f5b037.png?authuser=5&hl=he)
כאן מתבצעת גם בדיקת SafeBrowsing. אם נראה שהדומיין ונתוני התגובה תואמים לאתר זדוני ידוע, סימן שה-thread של הרשת כדי להציג דף אזהרה. בנוסף, Cross Origin RBlocking (CORB) מתבצעת בדיקה כדי לוודא שכתובות אתרים רגישות לא מגיעים לתהליך של רינדור.
שלב 4: מוצאים תהליך של רינדור
לאחר שכל הבדיקות יסתיימו ושרשור הרשת יהיה בטוח שהדפדפן צריך לנווט אל האתר המבוקש, ה-thread של הרשת מסמן ל-UI בשרשור שהנתונים מוכנים. לאחר מכן, ה-thread של ממשק המשתמש מוצא של כלי הרינדור כדי להמשיך בעיבוד של דף האינטרנט.
![חיפוש תהליך של רינדור](https://developer.chrome.com/static/blog/inside-browser-part2/image/find-renderer-process-4d4055665d4a7.png?authuser=5&hl=he)
מכיוון שיכולות לחלוף כמה מאות אלפיות שנייה עד לקבלת תשובה, בקשת הרשת כדי לזרז את התהליך הזה. כאשר ה-thread של ממשק המשתמש שולח בקשה לכתובת URL אל בשרשור של הרשת בשלב 2, הוא כבר יודע לאיזה אתר הם מנווטים. ה-thread של ממשק המשתמש מנסה למצוא או להתחיל תהליך רינדור באופן יזום במקביל לבקשת הרשת. כך, אם הכל הולך כמצופה, תהליך רינדור כבר נמצא במצב המתנה כאשר ה-thread של הרשת נתונים שהתקבלו. ייתכן שלא ייעשה שימוש בתהליך ההמתנה הזה אם ההפניה האוטומטית מפנה בין אתרים, במקרה כזה, ייתכן שיידרש תהליך אחר.
שלב 5: שמירת הניווט
כשהנתונים ותהליך הרינדור מוכנים, IPC נשלח מתהליך הדפדפן אל של ה-רינדור כדי לשמור את הניווט. הוא גם מעביר את מקור הנתונים כך שהרינדור יכול להמשיך לקבל נתוני HTML. אחרי שבתהליך הדפדפן יש אישור לכך התרחש בתהליך הרינדור, הניווט הושלם ושלב טעינת המסמך מתחיל.
בשלב הזה, סרגל הכתובות מתעדכן, ואינדיקטור האבטחה וממשק המשתמש של הגדרות האתר משקפים את פרטי האתר של הדף החדש. היסטוריית הסשנים של הכרטיסייה תעודכן, כך שממשיכים לדף הקודם/הבא. יעברו דרך האתר שאליו עברתם עכשיו. כדי להקל על שחזור כרטיסיות או סשן כשסוגרים כרטיסייה או חלון, היסטוריית הסשן נשמרת בדיסק.
![שמירת הניווט](https://developer.chrome.com/static/blog/inside-browser-part2/image/commit-navigation-bc2943921c6f6.png?authuser=5&hl=he)
שלב נוסף: הטעינה הראשונית הושלמה
לאחר ביצוע הניווט, תהליך הרינדור ממשיך לטעון משאבים ומעבד
הדף הזה. בפוסט הבא נעבור על הפרטים לגבי השלב הזה. אחרי כלי הרינדור
לעבד 'סיום' הוא שולח כתובת IPC בחזרה לתהליך הדפדפן (אחרי כל
onload
אירועים הופעלו בכל הפריימים בדף וההפעלה שלהם הסתיימה. בשלב הזה,
ה-thread של ממשק המשתמש מפסיק את העיגול של הטעינה בכרטיסייה.
אני אומר "Finishes" (סיום), כי JavaScript בצד הלקוח עדיין יכול להיטען למשאבים נוספים ולהצגת תצוגות חדשות לאחר מכן.
![סיום הטעינה של הדף בטעינה](https://developer.chrome.com/static/blog/inside-browser-part2/image/page-finish-loading-1bee6888e9e56.png?authuser=5&hl=he)
ניווט לאתר אחר
הניווט הפשוט הושלם. אבל מה קורה אם משתמש מוסיף כתובת URL שונה לסרגל הכתובות
שוב? ובכן, תהליך הדפדפן עובר את אותם שלבים כדי לנווט לאתר האחר.
אבל לפני כן, הוא צריך לבדוק באתר שעבר עיבוד אם כבר יש לו עניין
beforeunload
.
באפשרות beforeunload
ליצור את ההודעה 'לעזוב את האתר?' מוצגת התראה כשמנסים לנווט מחוץ לכרטיסייה או לסגור אותה.
כל מה שבתוך כרטיסייה, כולל קוד JavaScript, מטופל על ידי תהליך הרינדור, כך
תהליך הדפדפן צריך לבדוק עם תהליך הרינדור הנוכחי כשמתקבלת בקשת ניווט חדשה.
![הגורם המטפל באירוע beforeunload](https://developer.chrome.com/static/blog/inside-browser-part2/image/beforeunload-event-handle-53b6fa7dd9be3.png?authuser=5&hl=he)
אם הניווט התחיל מתהליך הרינדור (למשל, משתמש לחץ על קישור או
JavaScript בצד הלקוח הריץ window.location = "https://newsite.com"
) את תהליך הרינדור
בודק קודם את beforeunload
handlers. לאחר מכן, הוא עובר את אותו תהליך כמו תהליך בדפדפן
הופעל ניווט. ההבדל היחיד הוא שבקשת הניווט החלה
תהליך רינדור לתהליך הדפדפן.
כשהניווט החדש מתבצע לאתר שונה מזה שעבר רינדור כרגע, תתבצע רינדור נפרד
נשלחת כדי לטפל בניווט החדש בזמן שתהליך העיבוד הנוכחי נשמר
לטפל באירועים כמו unload
. מידע נוסף זמין בסקירה כללית של מצבי מחזור החיים של הדף.
ואיך אפשר להתחבר לאירועים
API של מחזור החיים של הדף.
![ניווט חדש והסרת טעינה](https://developer.chrome.com/static/blog/inside-browser-part2/image/new-navigation-unload-29ee714c3fcf4.png?authuser=5&hl=he)
במקרה של Service Worker
אחד מהשינויים האחרונים בתהליך ניווט זה הוא service worker. קובץ שירות (service worker) הוא שיטה לכתוב שרת proxy של רשת בקוד האפליקציה; ומאפשרת למפתחי אתרים לקבל יותר שליטה על לשמור במטמון באופן מקומי ומתי לקבל נתונים חדשים מהרשת. אם Service Worker מוגדר לטעון את הדף מהמטמון, אין צורך לבקש את הנתונים מהרשת.
מה שחשוב לזכור הוא ש-Service Worker הוא קוד JavaScript שרץ בכלי רינדור תהליך האימות. אבל כשבקשת הניווט מתקבלת, איך תהליך הדפדפן יודע שיש לאתר קובץ שירות (service worker)?
![חיפוש היקף של Service Worker](https://developer.chrome.com/static/blog/inside-browser-part2/image/service-worker-scope-look-f48a8d509535a.png?authuser=5&hl=he)
כש-Service Worker רשום, ההיקף של Service Worker נשמר כחומר עזר (ניתן לקרוא מידע נוסף על היקף ב המאמר בנושא מחזור החיים של Service Worker). במהלך ניווט, שרשור הרשת בודק את הדומיין מול קובץ שירות רשום שלו, אם קובץ שירות (service worker) רשום בכתובת ה-URL הזו, ה-thread של ה-UI ימצא תהליך של רינדור כדי להריץ את הקוד של Service Worker. Service Worker עשוי לטעון נתונים מהמטמון, וכך לבטל את השימוש את הצורך לבקש נתונים מהרשת, או לבקש משאבים חדשים מהרשת.
![ניווט Workworker](https://developer.chrome.com/static/blog/inside-browser-part2/image/serviceworker-navigation-8576df1bffcf9.png?authuser=5&hl=he)
טעינה מראש של הניווט
אפשר לראות את המעבר הלוך ושוב בין תהליך הדפדפן לתהליך הרינדור עלול לגרום לעיכובים אם קובץ שירות (service worker) מחליט בסופו של דבר לבקש נתונים מהרשת. הטעינה מראש של הניווט היא מנגנון להאצה לטעון משאבים במקביל להפעלה של Service Worker. היא מסמנת את הבקשות האלה בכותרת, וכך השרתים יכולים להחליט לשלוח תוכן שונה הבקשות האלה; לדוגמה, הצגת נתונים מעודכנים במקום מסמך שלם.
![טעינה מראש של הניווט](https://developer.chrome.com/static/blog/inside-browser-part2/image/navigation-preload-a859b1ad065e3.png?authuser=5&hl=he)
סיכום
בפוסט הזה, בדקנו מה קורה במהלך הניווט ואיך קוד אפליקציית האינטרנט שלכם ככותרות תגובה ו-JavaScript בצד הלקוח יוצרים אינטראקציה עם הדפדפן. הכרת השלבים בדפדפן מקבל נתונים מהרשת, קל יותר להבין למה ממשקי API כמו ניווט פותחו מראש. בפוסט הבא נתעמק באופן שבו הדפדפן מעריך HTML/CSS/JavaScript כדי לעבד דפים.
נהנית מהפוסט? אם יש לך שאלות או הצעות לגבי פוסט עתידי, אשמח נשמח לשמוע מכם בקטע התגובות בהמשך או ב-@kosamari ב-Twitter.