Skip to content

Deschiderea primește firul până când e vopsită

Vitalie requested to merge 69_opening-owns-the-wire into main

Pe paginile cărora serverul le desenează deschiderea — prima pagină și pagina de produs — pachetul de intrare, indiciile lui de modul, chunk-ul de traduceri și cele două fonturi nu mai stau în cap. Sunt numite într-un bloc de date, iar un bloc scurt de la finalul corpului le pornește când poza deschiderii s-a încărcat: sau la eroarea ei, sau după două secunde, ca aplicația să pornească oricum.

Regula, într-o frază: firul e al deschiderii până când e vopsită.

De ce

Cauza scrisă în #69 (closed) era greșită și am corectat-o acolo, cu măsurători. Pe scurt: Lantern include în graful celei mai mari vopsiri toate cererile terminate înainte de vopsirea observată, indiferent de prioritate, și le simulează pe legătura lentă. Pe prima pagină erau 9 cereri și 277 KB — dintre care 132 KB de JavaScript care ajungeau cu o milisecundă înaintea pozei.

fetchpriority="low" livrat în #44 (closed) nu oprește asta: peste HTTP/2 printr-un CDN prioritatea e un sfat, și se vede în urmă — poza cerută „High" și pachetul cerut „Low" se termină la o milisecundă distanță. Ce decide ordinea e care cereri există, nu ce pretind ele.

Fonturile pleacă din același motiv, descoperit după prima variantă: cât timp se vede deschiderea, pe ecran nu e nicio literă — serverul scrie o poză în #root și atât, iar blocul pentru crawlere stă într-un <noscript>. Odată ce JavaScript-ul a ieșit de pe fir, cele două fonturi s-au terminat mai devreme și au intrat ELE în fereastră; pe pagina de produs asta singură a mutat cea mai mare vopsire de la 1.338 la 1.639 ms. Se întorc odată cu modulele, deci sunt gata cu mult înainte ca aplicația să deseneze primul cuvânt.

Ce se măsoară

Bancă locală care servește documentul în forma producției — același cap, aceleași 37 de taguri, aceiași 70 KB de CSS în document, aceeași poză de 79.318 octeți — peste o legătură de 60 ms și 1,2 MB/s împărțită de toate cererile. Fereastra dinaintea vopsirii observate iese aceeași ca pe producție: 9 cereri, 270.260 de octeți, cu poza la 380 ms și pachetul la 401 ms.

prima pagină înainte după
cereri terminate înainte de vopsirea observată 8 3
octeți 184.799 100.225
poza hero, în urma reală 382 ms 251 ms
vopsirea observată 401 ms 270 ms

Poza ajunge cu 131 ms mai devreme fiindcă are firul pentru ea. Pachetul de intrare ajunge cu 74 ms mai târziu (405 → 479 ms): aceiași octeți, unul după altul în loc de amestecat.

Ce nu se schimbă

fetchpriority="low" rămâne unde e — la prima vopsire prioritatea chiar contează, și acolo a adus 1,33 s în #44 (closed). Paginile fără deschidere desenată de server (colecții, articole, /about) păstrează capul exact cum îl scrie vite build, fiindcă acolo prima vopsire ESTE pachetul.

Siguranță

  • Blocul de pornire e permis prin amprenta propriului text în script-src, nu prin 'unsafe-inline' și nu printr-un nonce. Amprenta se calculează din text, deci cele două nu pot să se despartă.
  • Fiecare drum se termină cu o pornire: încărcare, eroare, plafon de două secunde, poză deja în memorie, pagină fără poză.
  • Ordinea față de /config.js e păstrată prin DOMContentLoaded — scripturile amânate sunt garantate rulate până la el, iar aplicația citește window.__RUNTIME_CONFIG__ din prima clipă.
  • Dacă vite build scrie într-o zi capul altfel, sau documentul n-are unde primi blocul, nu se ridică nimic și pagina pleacă exact cum a venit.
  • Verificat pe viu în browser, pe bancă: magazinul pornește, cele șase secțiuni se randează, ambele fonturi ajung loaded, și pornește la fel de bine când poza răspunde 404.

Un control care merită citit

Am servit aceeași pagină cu modulele scoase din cap și FĂRĂ blocul de pornire — adică o pagină care nu pornește niciodată. Prima schimbare vizibilă vine la 104–129 ms, față de 212–222 ms cu capul de azi. Scoaterea modulelor din cap nu întârzie desenul; îl grăbește.

Merge request reports