Ein Blick hinter die Kulissen eines modernen Webbrowsers (Teil 2)

Mariko Kosaka

Was passiert bei der Navigation?

Dieser Artikel ist der zweite Teil einer vierteiligen Blogreihe, in der es um die Funktionsweise von Chrome geht. Im vorherigen Post haben wir uns damit beschäftigt, Prozesse und Threads verarbeiten verschiedene Teile eines Browsers. In diesem Beitrag gehen wir näher darauf ein, alle Prozesse und Threads kommunizieren, um eine Website anzuzeigen.

Sehen wir uns einen einfachen Anwendungsfall für das Surfen im Web an: Sie geben eine URL in einen Browser ein, dann den ruft Daten aus dem Internet ab und zeigt eine Seite an. In diesem Beitrag konzentrieren wir uns auf den Teil, in dem ein Ein Nutzer eine Website anfordert und der Browser bereitet sich auf das Rendern der Seite vor. Dies wird auch als Navigation bezeichnet.

Es beginnt mit einem Browser-Prozess

<ph type="x-smartling-placeholder">
</ph> Browserprozesse <ph type="x-smartling-placeholder">
</ph> Abbildung 1: Browser-Benutzeroberfläche oben, Diagramm des Browserprozesses mit Benutzeroberfläche, Netzwerk und Speicher den Thread unten

Wie wir bereits in Teil 1: CPU-, GPU-, Arbeitsspeicher- und Multi-Prozess-Architektur, wird alles außerhalb eines Tabs vom Browserprozess verarbeitet. Der Browserprozess umfasst Threads wie den UI-Thread, der Schaltflächen und Eingabefelder der der Netzwerk-Thread, der Daten aus dem Internet empfängt, den Speicherthread, der den Zugriff auf die Dateien und mehr steuert. Wenn Sie eine URL in die Adresse eingeben, wird Ihre Eingabe vom UI-Thread des Browserprozesses verarbeitet.

Eine einfache Navigation

Schritt 1: Eingabe verarbeiten

Wenn ein Nutzer mit der Eingabe in die Adressleiste beginnt, wird als Erstes gefragt: „Ist das Suchanfrage oder URL?“. In Chrome ist die Adressleiste auch ein Eingabefeld für die Suche. Der UI-Thread muss parsen und entscheiden, ob Sie an eine Suchmaschine oder die angeforderte Website weitergeleitet werden sollen.

<ph type="x-smartling-placeholder">
</ph> Nutzereingabe verarbeiten <ph type="x-smartling-placeholder">
</ph> Abbildung 1: UI-Thread, in dem gefragt wird, ob die Eingabe eine Suchanfrage oder eine URL ist

Schritt 2: Navigation starten

Wenn ein Nutzer die Eingabetaste drückt, initiiert der UI-Thread einen Netzwerkaufruf, um Websiteinhalte abzurufen. Rotierendes Ladesymbol wird in der Ecke eines Tabs angezeigt und der Netzwerk-Thread durchläuft entsprechende Protokolle, DNS-Lookup und Herstellen einer TLS-Verbindung für die Anfrage.

<ph type="x-smartling-placeholder">
</ph> Navigationsbeginn <ph type="x-smartling-placeholder">
</ph> Abbildung 2: UI-Thread, der mit dem Netzwerk-Thread kommuniziert, um zu mysite.com zu gelangen

An dieser Stelle erhält der Netzwerk-Thread möglicherweise einen Server-Weiterleitungs-Header wie HTTP 301. In diesem Fall Der Netzwerk-Thread kommuniziert mit dem UI-Thread, dass der Server eine Weiterleitung anfordert. Gehen Sie dann so vor: wird eine weitere URL-Anfrage initiiert.

Schritt 3: Antwort lesen

<ph type="x-smartling-placeholder">
</ph> HTTP-Antwort <ph type="x-smartling-placeholder">
</ph> Abbildung 3: Antwort-Header mit Content-Type und Nutzlast, bei der es sich um die tatsächlichen Daten handelt.

Sobald der Antworttext (Nutzlast) eingeht, prüft der Netzwerkthread die ersten Byte des Streams hinzufügen. Im Content-Type-Header der Antwort sollte angegeben sein, um welchen Datentyp es sich handelt. aber da diese möglicherweise fehlen oder falsch sind, MIME-Typ-Sniffing wird hier erledigt. Das ist ein „kniffliges Geschäft“ wie im Quellcode kommentiert. Sie können den Kommentar lesen, um zu sehen, wie verschiedene Browser Content-Typ/Nutzlast-Paare verarbeiten.

Wenn die Antwort eine HTML-Datei ist, werden die Daten im nächsten Schritt an den Renderer übergeben. Wenn es sich jedoch um eine ZIP-Datei oder eine andere Datei handelt, handelt es sich um eine Download-Anfrage. müssen die Daten an den Download-Manager übergeben werden.

<ph type="x-smartling-placeholder">
</ph> MIME-Typ-Sniffing <ph type="x-smartling-placeholder">
</ph> Abbildung 4: Netzwerk-Thread, in dem gefragt wird, ob die Antwortdaten HTML von einer sicheren Website sind

Hier findet auch die SafeBrowsing-Prüfung statt. Wenn die Domain- und Antwortdaten offenbar mit einer bekannten schädlichen Website übereinstimmen, ist der Netzwerkthread um eine Warnseite anzuzeigen. Außerdem Fross-Orire-Read-Blocking (CORB) um sicherzustellen, dass sensible Website-übergreifende gelangen die Daten nicht in den Renderer-Prozess.

Schritt 4: Renderer-Prozess finden

Sobald alle Prüfungen abgeschlossen sind und der Netzwerk-Thread sicher ist, dass der Browser zur angefragte Website an, teilt der Netzwerk-Thread dem UI-Thread mit, dass die Daten bereit sind. findet dann eine Renderer-Prozess für das Rendern der Webseite.

<ph type="x-smartling-placeholder">
</ph> Renderer-Prozess suchen <ph type="x-smartling-placeholder">
</ph> Abbildung 5: Netzwerk-Thread, der den UI-Thread anweist, den Renderer-Prozess zu finden

Da es mehrere hundert Millisekunden dauern kann, bis die Netzwerkanfrage eine Antwort zurückgibt, um diesen Prozess zu beschleunigen. Wenn der UI-Thread eine URL-Anfrage an mit dem Netzwerk-Thread in Schritt 2 verbunden ist, weiß schon, zu welcher Website er navigiert. Der UI-Thread versucht, parallel zur Netzwerkanfrage proaktiv einen Rendererprozess zu finden oder zu starten. Auf diese Weise Läuft alles erwartungsgemäß, befindet sich ein Renderer-Prozess bereits in der Standby-Position, wenn der Netzwerk-Thread empfangenen Daten. Dieser Standby-Prozess wird möglicherweise nicht verwendet, wenn die Navigation websiteübergreifend, in In diesem Fall ist möglicherweise ein anderer Prozess erforderlich.

Schritt 5: Commit-Navigation

Da die Daten und der Renderer-Prozess nun bereit sind, wird ein IPC vom Browserprozess an den Renderer-Prozess, um die Navigation zu übergeben. Sie leitet auch den Datenstream weiter, damit der Renderer kann weiterhin HTML-Daten empfangen. Sobald der Browser-Prozess die Bestätigung erhält, dass der Commit durchgeführt wurde, im Renderer-Prozess stattgefunden hat, ist die Navigation abgeschlossen und die Phase des Dokumentladevorgangs ist abgeschlossen. beginnt.

Jetzt wird die Adressleiste aktualisiert und die Benutzeroberfläche für die Sicherheitsanzeige und die Website-Einstellungen Website-Informationen der neuen Seite. Der Sitzungsverlauf für den Tab wird aktualisiert, sodass navigieren Sie durch die Website, zu der Sie gerade navigiert sind. Um die Wiederherstellung von Tabs/Sitzungen zu erleichtern Wenn Sie einen Tab oder ein Fenster schließen, wird der Sitzungsverlauf auf dem Laufwerk gespeichert.

<ph type="x-smartling-placeholder">
</ph> Commit für Navigation durchführen <ph type="x-smartling-placeholder">
</ph> Abbildung 6: IPC zwischen Browser und Renderer-Prozessen, die das Rendern der Seite anfordern

Zusätzlicher Schritt: Anfänglicher Ladevorgang abgeschlossen

Nachdem die Navigation per Commit übertragen wurde, lädt der Renderer-Prozess weiter Ressourcen und rendert Seite. Im nächsten Beitrag erfahren Sie, was in dieser Phase geschieht. Sobald der Renderer Prozess „beendet“ wird ein IPC zurück an den Browserprozess gesendet. onload-Ereignisse wurden für alle Frames auf der Seite ausgelöst und ihre Ausführung ist abgeschlossen. An dieser Stelle stoppt der UI-Thread das Laden des rotierenden Ladesymbols auf dem Tab.

Ich sage „beendet“, weil clientseitiges JavaScript noch geladen werden kann zusätzliche Ressourcen zu erstellen und neue Ansichten zu rendern.

<ph type="x-smartling-placeholder">
</ph> Fertigstellen der Seite <ph type="x-smartling-placeholder">
</ph> Abbildung 7: IPC vom Renderer zum Browserprozess, um zu signalisieren, dass die Seite "geladen" ist

Die einfache Navigation war fertig! Aber was passiert, wenn ein Nutzer eine andere URL in die Adressleiste eingibt? noch einmal? Nun, der Browser-Prozess durchläuft dieselben Schritte, um zu den unterschiedlichen Websites zu navigieren. Zuvor muss jedoch mit der aktuell gerenderten Website geprüft werden, ob sie Interesse daran hat, Ereignis beforeunload.

beforeunload kann „Website verlassen?“ erstellen angezeigt, wenn Sie versuchen, eine Seite zu verlassen oder den Tab zu schließen. Alles auf einem Tab, einschließlich Ihres JavaScript-Codes, wird vom Renderer-Prozess verarbeitet. Der Browserprozess muss mit dem aktuellen Rendererprozess übereinstimmen, wenn eine neue Navigationsanfrage eingeht.

<ph type="x-smartling-placeholder">
</ph> „beforeunload“-Event-Handler <ph type="x-smartling-placeholder">
</ph> Abbildung 8: IPC vom Browserprozess zu einem Renderer-Prozess, mit dem die Übertragung Zu einer anderen Website navigieren

Wurde die Navigation über den Renderer-Prozess initiiert, z. B. wenn der Nutzer auf einen Link oder clientseitiges JavaScript ausgeführt hat window.location = "https://newsite.com") den Renderer-Prozess prüft zuerst beforeunload-Handler. Dann durchläuft sie denselben Prozess wie der Browserprozess. die Navigation gestartet haben. Der einzige Unterschied besteht darin, dass die Navigationsanfrage mit dem Browserprozess zu verknüpfen.

Wenn die neue Navigation zu einer anderen Website als der derzeit gerenderten Website führt, wird ein separates -Prozess wird aufgerufen, um die neue Navigation zu bearbeiten, während der aktuelle Render-Prozess verarbeiten Ereignisse wie unload. Weitere Informationen und wie Sie sich mithilfe von Page Lifecycle API.

<ph type="x-smartling-placeholder">
</ph> neue Navigation und Entladen <ph type="x-smartling-placeholder">
</ph> Abbildung 9: Zwei IPCs von einem Browserprozess zu einem neuen Renderer-Prozess, der angewiesen wird, die Seite zu rendern und den alten Renderer-Prozess anweisen, entladen zu werden,

Im Fall eines Service Workers

Eine kürzlich erfolgte Änderung an diesem Navigationsprozess ist die Einführung von Service Worker generiert. Mit einem Service Worker können Sie Netzwerk-Proxy in Ihrem Anwendungscode verwenden; So haben Webentwickler mehr Kontrolle darüber, und wann neue Daten aus dem Netzwerk abgerufen werden. Wenn der Service Worker so eingestellt ist, dass er die Seite lädt aus dem Cache, müssen die Daten nicht vom Netzwerk angefordert werden.

Denken Sie daran, dass es sich bei Service Worker um JavaScript-Code handelt, der in einem Renderer ausgeführt wird. . Woher weiß jedoch ein Browserprozess, dass auf der Website eine Navigationsanfrage eingeht, Service Worker?

<ph type="x-smartling-placeholder">
</ph> Service Worker-Bereichssuche <ph type="x-smartling-placeholder">
</ph> Abbildung 10: Netzwerkthread im Browserprozess, nach dem der Service Worker-Bereich abgerufen wird

Wenn ein Service Worker registriert wird, wird dessen Bereich als Referenz beibehalten (Weitere Informationen zum Umfang finden Sie in diesem Service Worker-Lebenszyklus). Bei einer Navigation prüft der Netzwerkthread die Domain mit dem registrierten Service Worker Wenn ein Service Worker für diese URL registriert ist, findet der UI-Thread einen Renderer-Prozess in um den Service Worker-Code auszuführen. Der Service Worker kann Daten aus dem Cache laden, Daten müssen aus dem Netzwerk angefordert werden. Eventuell werden auch neue Ressourcen vom Netzwerk angefordert.

<ph type="x-smartling-placeholder">
</ph> Serviceworker Navigation <ph type="x-smartling-placeholder">
</ph> Abbildung 11: UI-Thread in einem Browserprozess, der einen Renderer-Prozess zur Verarbeitung des Dienstes startet Arbeitnehmern; Ein Worker-Thread in einem Renderer-Prozess fordert dann Daten vom Netzwerk an.

Dieser Umlauf zwischen Browserprozess und Rendererprozess kann zu Verzögerungen führen. wenn sich der Service Worker entscheidet, Daten aus dem Netzwerk anzufordern. Mit der Funktion Navigationsvorabladen lässt sich dieser Vorgang beschleunigen. durch das parallele Laden von Ressourcen zum Start des Service Workers. Diese Anfragen werden mit einem Header gekennzeichnet, sodass die Server entscheiden können, ob sie andere Inhalte diese Anträge stellen; beispielsweise nur aktualisierte Daten anstelle eines vollständigen Dokuments.

<ph type="x-smartling-placeholder">
</ph> Navigationsvorabladen <ph type="x-smartling-placeholder">
</ph> Abbildung 12: UI-Thread in einem Browserprozess, der einen Renderer-Prozess zur Verarbeitung des Dienstes startet Worker beim gleichzeitigen Starten der Netzwerkanfrage

Zusammenfassung

In diesem Post haben wir uns damit befasst, was bei einer Navigation passiert und wie Ihr Webanwendungscode da Antwort-Header und clientseitiges JavaScript mit dem Browser interagieren. Browser mit den Schritten Daten aus dem Netzwerk abzurufen, erleichtert es zu verstehen, warum APIs wie die Navigation Vorabladen entwickelt wurden. Im nächsten Beitrag erfahren Sie, wie der Browser die HTML/CSS/JavaScript zum Rendern von Seiten.

Hat Ihnen der Beitrag gefallen? Wenn Sie Fragen oder Vorschläge für den nächsten Beitrag haben, findest du unten in den Kommentaren oder @kosamari auf Twitter.

<ph type="x-smartling-placeholder"></ph> Nächster Schritt: Innere Funktionsweise eines Renderer-Prozesses