Een kijkje in de moderne webbrowser (deel 2)

Mariko Kosaka

Wat gebeurt er tijdens de navigatie

Dit is deel 2 van een vierdelige blogserie over de interne werking van Chrome. In het vorige bericht hebben we gekeken hoe verschillende processen en threads omgaan met verschillende delen van een browser. In dit bericht gaan we dieper in op de manier waarop elk proces en elke thread communiceert om een ​​website weer te geven.

Laten we eens kijken naar een eenvoudig gebruiksvoorbeeld van surfen op het internet: u typt een URL in een browser, waarna de browser gegevens van internet ophaalt en een pagina weergeeft. In dit bericht concentreren we ons op het gedeelte waarin een gebruiker een site opvraagt ​​en de browser zich voorbereidt op het weergeven van een pagina, ook wel navigatie genoemd.

Het begint met een browserproces

Browserprocessen
Figuur 1: Browser-UI bovenaan, diagram van het browserproces met UI, netwerk en opslagthread onderaan

Zoals we in deel 1 hebben besproken: CPU, GPU, geheugen en architectuur met meerdere processen , wordt alles buiten een tabblad afgehandeld door het browserproces. Het browserproces heeft threads zoals de UI-thread die knoppen en invoervelden van de browser tekent, de netwerkthread die zich bezighoudt met de netwerkstack om gegevens van internet te ontvangen, de opslagthread die de toegang tot de bestanden regelt en meer. Wanneer u een URL in de adresbalk typt, wordt uw invoer verwerkt door de UI-thread van het browserproces.

Een eenvoudige navigatie

Stap 1: Omgaan met input

Wanneer een gebruiker in de adresbalk begint te typen, is het eerste wat de UI-thread vraagt: "Is dit een zoekopdracht of een URL?". In Chrome is de adresbalk ook een zoekinvoerveld, dus de UI-thread moet worden geparseerd en beslissen of u naar een zoekmachine wordt gestuurd of naar de site die u hebt opgevraagd.

Het verwerken van gebruikersinvoer
Figuur 1: UI-thread waarin wordt gevraagd of de invoer een zoekopdracht of een URL is

Stap 2: Start de navigatie

Wanneer een gebruiker op enter drukt, initieert de UI-thread een netwerkoproep om site-inhoud op te halen. De laadspinner wordt weergegeven op de hoek van een tabblad en de netwerkthread doorloopt de juiste protocollen, zoals DNS-lookup en het tot stand brengen van TLS-verbinding voor het verzoek.

Navigatie starten
Figuur 2: de UI-thread praat met de netwerkthread om naar mysite.com te navigeren

Op dit punt ontvangt de netwerkthread mogelijk een serveromleidingsheader zoals HTTP 301. In dat geval communiceert de netwerkthread met de UI-thread dat de server om omleiding vraagt. Vervolgens wordt een nieuw URL-verzoek gestart.

Stap 3: Lees het antwoord

HTTP-antwoord
Figuur 3: antwoordheader die Content-Type en payload bevat, wat de feitelijke gegevens zijn

Zodra de antwoordtekst (payload) binnenkomt, kijkt de netwerkthread indien nodig naar de eerste paar bytes van de stream. De Content-Type-header van het antwoord zou moeten aangeven welk type gegevens het is, maar omdat deze mogelijk ontbreken of onjuist zijn, wordt hier MIME-type-snuffelen uitgevoerd. Dit is een "lastige zaak", zoals opgemerkt in de broncode . U kunt de opmerking lezen om te zien hoe verschillende browsers omgaan met inhoudstype/payload-paren.

Als het antwoord een HTML-bestand is, is de volgende stap het doorgeven van de gegevens aan het rendererproces, maar als het een zip-bestand of een ander bestand is, betekent dit dat het een downloadverzoek is, dus moeten ze de gegevens doorgeven aan downloadbeheerder.

MIME-type snuiven
Figuur 4: Netwerkthread waarin wordt gevraagd of de antwoordgegevens HTML zijn van een veilige site

Dit is ook waar de SafeBrowsing- controle plaatsvindt. Als het domein en de responsgegevens lijken overeen te komen met een bekende kwaadaardige site, waarschuwt de netwerkthread om een ​​waarschuwingspagina weer te geven. Bovendien vindt er een C ross O rigin Read B- vergrendeling ( CORB ) -controle plaats om ervoor te zorgen dat gevoelige cross-site-gegevens het rendererproces niet bereiken.

Stap 4: Zoek een rendererproces

Zodra alle controles zijn uitgevoerd en de netwerkthread er zeker van is dat de browser naar de gevraagde site moet navigeren, vertelt de netwerkthread aan de UI-thread dat de gegevens gereed zijn. UI-thread vindt vervolgens een rendererproces om door te gaan met het renderen van de webpagina.

Vind het rendererproces
Figuur 5: Netwerkthread die de UI-thread vertelt om het Renderer-proces te vinden

Omdat het netwerkverzoek enkele honderden milliseconden kan duren voordat er een reactie terugkomt, wordt een optimalisatie toegepast om dit proces te versnellen. Wanneer de UI-thread bij stap 2 een URL-verzoek naar de netwerkthread verzendt, weet deze al naar welke site ze navigeren. De UI-thread probeert parallel aan het netwerkverzoek proactief een rendererproces te vinden of te starten. Op deze manier bevindt een rendererproces zich, als alles volgens verwachting verloopt, al in de standby-positie wanneer de netwerkthread gegevens ontvangt. Dit standby-proces wordt mogelijk niet gebruikt als de navigatie naar andere sites verwijst, in welk geval een ander proces nodig kan zijn.

Stap 5: Navigatie vastleggen

Nu de gegevens en het rendererproces gereed zijn, wordt een IPC van het browserproces naar het rendererproces verzonden om de navigatie vast te leggen. Het geeft ook de gegevensstroom door, zodat het rendererproces HTML-gegevens kan blijven ontvangen. Zodra het browserproces de bevestiging hoort dat de commit heeft plaatsgevonden in het rendererproces, is de navigatie voltooid en begint de fase van het laden van het document.

Op dit punt wordt de adresbalk bijgewerkt en geven de beveiligingsindicator en de gebruikersinterface van de site-instellingen de site-informatie van de nieuwe pagina weer. De sessiegeschiedenis voor het tabblad wordt bijgewerkt, zodat u met de knoppen Terug/Vooruit door de site kunt bladeren waar u zojuist naartoe bent genavigeerd. Om het herstel van tabbladen/sessies te vergemakkelijken wanneer u een tabblad of venster sluit, wordt de sessiegeschiedenis op schijf opgeslagen.

Voer de navigatie uit
Figuur 6: IPC tussen de browser en de rendererprocessen, met het verzoek om de pagina weer te geven

Extra stap: Initiële belasting voltooid

Zodra de navigatie is vastgelegd, gaat het weergaveproces door met het laden van bronnen en wordt de pagina weergegeven. In het volgende bericht zullen we de details bespreken van wat er in dit stadium gebeurt. Zodra het rendererproces het renderen "voltooid" heeft, stuurt het een IPC terug naar het browserproces (dit is nadat alle onload gebeurtenissen op alle frames op de pagina zijn geactiveerd en zijn uitgevoerd). Op dit punt stopt de UI-thread de laadspinner op het tabblad.

Ik zeg "voltooit", omdat JavaScript aan de clientzijde na dit punt nog steeds extra bronnen kan laden en nieuwe weergaven kan weergeven.

Pagina klaar met laden
Figuur 7: IPC van de renderer naar het browserproces om te melden dat de pagina is "geladen"

De eenvoudige navigatie was voltooid! Maar wat gebeurt er als een gebruiker opnieuw een andere URL in de adresbalk plaatst? Welnu, het browserproces doorloopt dezelfde stappen om naar de andere site te navigeren. Maar voordat het dat kan doen, moet het bij de momenteel weergegeven site controleren of het de gebeurtenis beforeunload belangrijk vindt.

beforeunload kan "Deze site verlaten?" waarschuwing wanneer u probeert weg te navigeren of het tabblad te sluiten. Alles binnen een tabblad, inclusief uw JavaScript-code, wordt afgehandeld door het rendererproces, dus het browserproces moet het huidige rendererproces controleren wanneer er een nieuw navigatieverzoek binnenkomt.

beforeunload gebeurtenishandler
Figuur 8: IPC van het browserproces naar een rendererproces dat aangeeft dat het op het punt staat naar een andere site te navigeren

Als de navigatie is gestart vanuit het rendererproces (zoals de gebruiker op een link heeft geklikt of JavaScript aan de clientzijde heeft uitgevoerd window.location = "https://newsite.com" ), controleert het rendererproces eerst beforeunload de handlers worden verwijderd. Vervolgens doorloopt het hetzelfde proces als de door het browserproces geïnitieerde navigatie. Het enige verschil is dat het navigatieverzoek van het rendererproces naar het browserproces wordt gestart.

Wanneer de nieuwe navigatie naar een andere site wordt gemaakt dan de momenteel weergegeven site, wordt een afzonderlijk weergaveproces ingeschakeld om de nieuwe navigatie af te handelen, terwijl het huidige weergaveproces behouden blijft om gebeurtenissen zoals unload af te handelen. Bekijk voor meer informatie een overzicht van de levenscyclusstatussen van pagina's en hoe u kunt aansluiten bij gebeurtenissen met de Page Lifecycle API .

nieuwe navigatie en lossen
Afbeelding 9: 2 IPC's van een browserproces naar een nieuw rendererproces dat aangeeft dat de pagina moet worden weergegeven en dat het oude rendererproces moet worden verwijderd

In het geval van een servicemedewerker

Een recente verandering in dit navigatieproces is de introductie van servicemedewerkers . Service worker is een manier om netwerkproxy in uw applicatiecode te schrijven; waardoor webontwikkelaars meer controle hebben over wat ze lokaal in de cache moeten opslaan en wanneer ze nieuwe gegevens uit het netwerk moeten halen. Als de servicemedewerker is ingesteld om de pagina uit de cache te laden, is het niet nodig om de gegevens op te vragen bij het netwerk.

Het belangrijkste om te onthouden is dat de servicemedewerker JavaScript-code is die wordt uitgevoerd in een rendererproces. Maar wanneer het navigatieverzoek binnenkomt, hoe weet een browserproces dan dat de site een servicemedewerker heeft?

Bereik van servicemedewerker opzoeken
Figuur 10: de netwerkthread in het browserproces waarbij de reikwijdte van de servicewerker wordt opgezocht

Wanneer een servicemedewerker wordt geregistreerd, wordt de reikwijdte van de servicemedewerker als referentie bewaard (u kunt meer over de reikwijdte lezen in dit artikel The Service Worker Lifecycle ). Wanneer er een navigatie plaatsvindt, controleert de netwerkthread het domein aan de hand van geregistreerde servicemedewerkers. Als een servicemedewerker is geregistreerd voor die URL, vindt de UI-thread een rendererproces om de servicemedewerkercode uit te voeren. De servicemedewerker kan gegevens uit de cache laden, waardoor het niet meer nodig is gegevens op te vragen bij het netwerk, of hij kan nieuwe bronnen opvragen bij het netwerk.

navigatie voor servicemedewerkers
Figuur 11: de UI-thread in een browserproces dat een rendererproces opstart om servicemedewerkers af te handelen; een werkthread in een rendererproces vraagt ​​vervolgens gegevens op van het netwerk

U kunt zien dat deze heen- en terugreis tussen het browserproces en het rendererproces tot vertragingen kan leiden als de servicemedewerker uiteindelijk besluit gegevens op te vragen bij het netwerk. Navigatie Preload is een mechanisme om dit proces te versnellen door bronnen parallel te laden met het opstarten van de servicemedewerker. Het markeert deze verzoeken met een header, waardoor servers kunnen beslissen om verschillende inhoud voor deze verzoeken te verzenden; bijvoorbeeld alleen bijgewerkte gegevens in plaats van een volledig document.

Navigatie vooraf geladen
Afbeelding 12: de UI-thread in een browserproces, waarbij een rendererproces wordt gestart om de servicemedewerker af te handelen, terwijl tegelijkertijd netwerkverzoeken worden gestart

Afronden

In dit bericht hebben we gekeken naar wat er gebeurt tijdens een navigatie en hoe uw webapplicatiecode, zoals responsheaders en client-side JavaScript, met de browser interageert. Als u weet welke stappen de browser doorloopt om gegevens uit het netwerk te halen, wordt het gemakkelijker te begrijpen waarom API's zoals het vooraf laden van navigatie zijn ontwikkeld. In het volgende bericht gaan we dieper in op hoe de browser onze HTML/CSS/JavaScript evalueert om pagina's weer te geven.

Vond je het bericht leuk? Als je vragen of suggesties hebt voor het toekomstige bericht, hoor ik graag van je in het commentaargedeelte hieronder of via @kosamari op Twitter.

Volgende: Innerlijke werking van een Renderer-proces