Web Performance

De ce site-ul tău ar trebui să trimită mai puține cereri, nu unele mai mici

Fișierele minuscule nu sunt gratuite. HTTP-ul modern a făcut costul cererilor mai mic, nu irelevant.

The Wux Webtools Team The Wux Webtools Team 11 min citire Asistat de AI, revizuit de oameni
A stylized browser waterfall showing many small requests simplified into fewer intentional requests.
Cuprins
  1. Mitul confortabil al ideii „doar fă fiecare fișier mai mic”
  2. Cererile nu înseamnă doar bytes
  3. „Dar HTTP/2 a rezolvat asta”, în mare parte nu
  4. Cascada este locul în care se află adevărul
  5. Fișierele mai mici încă contează — doar că nu în mod egal
  6. Costurile ascunse ale multor fișiere mici
  7. 1. Descoperire târzie
  8. 2. Costul headerelor
  9. 3. Întreruperea firului principal
  10. 4. Complexitatea cache-ului
  11. Bundlingul a revenit, dar cu discernământ
  12. Cererile terțe merită suspiciune suplimentară
  13. O listă practică pentru reducerea cererilor
  14. Elimină
  15. Combină cu grijă
  16. Amână
  17. Cache-uiește corect
  18. Măsoară din nou
  19. Cum arată binele

Mitul confortabil al ideii „doar fă fiecare fișier mai mic”

Timp de ani întregi, recomandările pentru performanța web au sunat simplu: comprimă tot, minifică tot, fă fiecare resursă mai mică.

Acest sfat este încă, în linii mari, corect. Un script de 40 KB este de obicei mai bun decât un script de 400 KB. O imagine optimizată este mai bună decât un export brut. Brotli, AVIF, minificarea CSS, tree shaking și sub-setarea fonturilor contează toate.

Dar pe multe site-uri de producție, problema mai mare nu mai este un singur fișier supradimensionat. Este numărul de lucruri pe care browserul trebuie să le ceară înainte ca pagina să pară utilizabilă.

O pagină poate arăta disciplinată ca dimensiuni ale fișierelor și totuși să fie lentă pentru că trimite 120 de cereri: fragmente CSS, bucăți JavaScript, taguri terțe, fișiere de font, pixeli de tracking, sprite-uri de pictograme, endpointuri JSON, preloads, beacons de analytics și revalidări ale cache-ului. Fiecare poate fi „mică”. Împreună, creează o cascadă lungă și fragilă.

Regula practică este aceasta: odată ce resursele individuale sunt comprimate rezonabil, reducerea numărului de cereri îmbunătățește adesea experiența utilizatorului mai mult decât economisirea câtorva kilobyți din fiecare fișier.

Cererile nu înseamnă doar bytes

O cerere de rețea nu este doar un transfer de date. Este o succesiune de operațiuni.

Browserul trebuie să descopere resursa, să decidă când să o preia, să o programeze în raport cu alte resurse, să trimită headere, să aștepte serverul, să primească headere, să parseze răspunsul, adesea să îl decomprime și apoi să facă ceva util cu el.

Acel „ceva util” poate fi costisitor. Un fișier JavaScript trebuie parsat, compilat și executat. Un fișier CSS poate bloca randarea. Un fișier de font poate întârzia textul lizibil sau poate provoca deplasări de layout. O imagine poate afecta elementul Largest Contentful Paint. Un script terț poate aduce propriul lanț de dependențe.

De aceea numărul de cereri contează în continuare, chiar și când fișierele sunt mici. Un script de 3 KB poate fi mai rău decât o imagine de 30 KB dacă blochează randarea, ajunge târziu și se execută pe firul principal în momentul nepotrivit.

Dacă citești un raport Lighthouse și te simți penalizat de zeci de avertismente separate, începe prin a te uita la cascada de cereri, nu la scorurile individuale. Avem un ghid practic în cum să citești un raport Lighthouse fără panică, dar versiunea scurtă este: găsește ce blochează prima randare și ce întârzie conținutul principal.

„Dar HTTP/2 a rezolvat asta”, în mare parte nu

HTTP/2 și HTTP/3 au schimbat economia cererilor. Au introdus multiplexarea, comprimarea headerelor și un comportament mai bun al conexiunilor. Pe scurt, browserele au devenit mult mai bune la trimiterea mai multor cereri peste mai puține conexiuni.

A fost o îmbunătățire reală. A eliminat și unele obiceiuri vechi, cum ar fi sprite-urile CSS extreme și bundle-urile concatenate uriașe, construite doar pentru a evita limitele de conexiuni.

Dar HTTP/2 nu a făcut cererile gratuite.

Multiplexarea ajută când multe resurse împart o conexiune, dar browserul tot trebuie să le prioritizeze. Serverele tot trebuie să răspundă. Clientul tot trebuie să proceseze fiecare răspuns. Congestia, pierderea pachetelor, negocierea TLS, interogarea DNS, cache miss-urile și presiunea pe firul principal încă există.

HTTP/3 îmbunătățește unele aspecte ale transportului, mai ales în jurul migrării conexiunilor și al head-of-line blocking la nivelul transportului. Nu elimină costul descoperirii, programării, descărcării, parsării și executării resurselor.

Așadar, obiectivul modern nu este „adună totul într-un singur fișier enorm”. Este „trimite mai puține cereri critice și fă cererile rămase intenționate”.

Cascada este locul în care se află adevărul

Problemele de performanță rareori se anunță într-o singură metrică. Ele apar ca formă.

Deschide panoul de rețea al browserului și uită-te la primele câteva secunde. Întreabă:

  • Câte cereri pornesc înainte să apară conținutul principal?
  • Care cereri blochează randarea?
  • Resursele importante sunt descoperite târziu?
  • Scripturile terțe concurează cu CSS, fonturile sau imaginile first-party?
  • Multe fișiere întorc răspunsuri 304 în loc să fie servite direct din cache?
  • Pictogramele, fonturile sau fragmentele de UI sunt împărțite în mai multe fișiere decât are nevoie pagina?

O pagină rapidă are, de obicei, o cascadă inițială plictisitoare. Un număr mic de resurse critice ajung devreme. Resursele necritice așteaptă. Scripturile terțe sunt amânate, limitate sau eliminate. Browserul nu este forțat să jongleze cu douăzeci de priorități înainte să poată picta pagina.

O pagină lentă are adesea o cascadă agitată: multe fișiere mici, multe origini și multe descoperiri târzii.

Fișierele mai mici încă contează — doar că nu în mod egal

Acesta nu este un argument împotriva comprimării sau optimizării. Este un argument împotriva optimizării bytes-ilor în timp ce ignori coordonarea.

Fișierele mai mici contează cel mai mult când resursa este mare, blochează randarea sau face parte din traseul conținutului principal. De exemplu:

  • Imaginea hero ar trebui să fie dimensionată și codificată corect.
  • CSS-ul care blochează randarea ar trebui să fie suplu.
  • JavaScript-ul necesar pentru prima interacțiune ar trebui să fie minim.
  • Fonturile ar trebui sub-setate, comprimate și limitate la greutățile folosite efectiv.

Fonturile sunt un exemplu comun. Echipele se obsedează adesea dacă un fișier de font are 24 KB sau 31 KB, în timp ce livrează șase greutăți, două stiluri și mai multe familii. Soluția mai bună nu este să economisești 7 KB dintr-un fișier. Este să trimiți mai puține fișiere de font. Dacă tipografia face parte din munca ta de performanță, fonturile web sunt încă unul dintre cele mai ușoare câștiguri pe majoritatea site-urilor.

Imaginile urmează același tipar. AVIF sau WebP pot economisi bytes importanți, dar trimiterea a zece imagini decorative în zona vizibilă inițial este tot un plan prost. Alege formate mai bune, da, dar întreabă și dacă fiecare imagine trebuie cerută deloc. Pentru decizii de format, ghidul nostru despre când AVIF bate WebP și când nu este un companion util pentru această muncă de reducere a numărului de cereri.

Costurile ascunse ale multor fișiere mici

Multe cereri mici tind să creeze probleme care nu apar dacă te uiți doar la totalul de bytes transferați.

1. Descoperire târzie

Browserele nu pot cere ceea ce nu au descoperit. Un fișier CSS poate referi un font. Un script poate importa alt script. O componentă poate cere JSON după hidratare. Fiecare dependență creează încă un pas în lanț.

Cu cât lanțul este mai adânc, cu atât munca importantă începe mai târziu.

2. Costul headerelor

Fiecare cerere și răspuns include headere. Comprimarea headerelor ajută, mai ales peste HTTP/2 și HTTP/3, dar nu elimină costul. Cookie-urile pot agrava mult situația. Dacă site-ul tău trimite cookie-uri mari cu fiecare cerere, resursele minuscule devin, în practică, mai puțin minuscule.

Acesta este unul dintre motivele pentru care resursele statice ar trebui să stea adesea pe căi sau domenii fără cookie-uri și de ce headerele de cache merită atenție. Dacă headerele se comportă ciudat în producție, depanarea redirectărilor și a headerelor HTTP este de obicei mai rapidă decât presupunerile.

3. Întreruperea firului principal

Multe bucăți JavaScript pot crea muncă repetată de parsare și execuție. Chiar dacă fiecare bucată este mică, browserul poate continua să se oprească pentru a evalua cod. Acest lucru poate afecta Interaction to Next Paint și poate face pagina să pară sacadată.

Utilizatorului nu îi pasă că fiecare fișier a fost mic. Îi pasă că atingerea unui meniu a durat 600 de milisecunde.

4. Complexitatea cache-ului

Împărțirea resurselor poate îmbunătăți cachingul atunci când este făcută cu grijă. Un bundle de vendor stabil și un bundle de aplicație care se schimbă pot fi o împărțire bună.

Dar fragmentarea excesivă poate avea efect invers. Mai multe fișiere înseamnă mai multe căutări în cache, mai multe ocazii de revalidare, mai multă coordonare a versiunilor și mai multe moduri de a invalida accidental resurse care nu trebuiau să se schimbe.

Bundlingul a revenit, dar cu discernământ

Prima eră a performanței web a iubit bundlingul pentru că browserele aveau limite stricte de conexiuni. Apoi a apărut HTTP/2 și multe echipe au virat puternic către code splitting agresiv. O parte a fost utilă. O parte a devenit superstiție.

Calea de mijloc rezonabilă este bundlingul conștient de rută.

Pentru un site tipic de marketing sau de conținut:

  • Include inline sau încarcă doar CSS-ul necesar pentru randarea inițială.
  • Păstrează JavaScript-ul global mic.
  • Evită împărțirea modulelor minuscule în cereri de rețea separate.
  • Amână funcțiile interactive care nu sunt necesare imediat.
  • Elimină scripturile terțe care nu își justifică costul.

Pentru o aplicație:

  • Împarte după rută sau funcționalitate majoră, nu după fiecare componentă.
  • Păstrează dependențele partajate stabile și cache-uibile.
  • Fă preload doar pentru resursele care vor fi sigur necesare curând.
  • Evită încărcarea codului de admin, dashboard, editor sau experiment pe paginile publice.
  • Măsoară costul interacțiunii, nu doar dimensiunea bundle-ului.

Bundlingul nu este automat bun. Code splittingul nu este automat bun. Întrebarea utilă este: ajută această împărțire browserul să livreze mai repede următoarea experiență semnificativă pentru utilizator?

Cererile terțe merită suspiciune suplimentară

Cererile first-party sunt cel puțin sub controlul tău. Cererile terțe sunt adesea mai lente, mai puțin previzibile și mai costisitoare decât par.

Un singur tag manager poate declanșa analytics, reclame, heatmaps, widgeturi de chat, testare A/B, instrumente de consimțământ și scripturi de personalizare. Fiecare furnizor poate aduce mai multe cereri. Unele vor rula devreme. Unele vor bloca firul principal. Unele se vor schimba fără procesul tău de release.

Cea mai bună optimizare pentru terți este ștergerea. A doua cea mai bună este amânarea.

Înainte de a adăuga un script terț, întreabă:

  • Trebuie acesta să se încarce înainte ca utilizatorul să vadă pagina?
  • Trebuie să se încarce pe fiecare pagină?
  • Poate să se încarce după consimțământ, interacțiune sau timp de inactivitate?
  • Cine îl deține intern?
  • Ce metrică dovedește că merită costul de performanță?

Aici performanța devine guvernanță. Cineva trebuie să aibă permisiunea să spună nu.

O listă practică pentru reducerea cererilor

Începe cu paginile care contează cel mai mult: homepage, pagina de prețuri, pagina de produs, checkout, signup sau principalele landing pages. Apoi parcurge cascada.

Elimină

  • Șterge JavaScript-ul și CSS-ul nefolosite.
  • Elimină experimentele vechi, pixelii abandonați și analytics-ul duplicat.
  • Renunță la greutățile de font și bibliotecile de pictograme nefolosite.
  • Înlocuiește imaginile decorative cu CSS acolo unde este potrivit.

Combină cu grijă

  • Grupează modulele JavaScript minuscule care se încarcă mereu împreună.
  • Unește fișierele CSS mici care blochează același traseu de randare.
  • Folosește sprite-uri SVG sau SVG inline pentru pictograme repetate atunci când reduc cererile fără să afecteze mentenabilitatea.

Amână

  • Încarcă lazy imaginile de sub zona vizibilă inițial.
  • Amână scripturile necritice până după prima pictare sau interacțiunea utilizatorului.
  • Încarcă comentarii, embeduri, hărți, chat și playere video doar când sunt necesare.

Cache-uiește corect

  • Folosește caching de lungă durată pentru resurse statice versionate.
  • Evită revalidarea inutilă pentru fișiere care se schimbă rar.
  • Păstrează HTML-ul proaspăt, dar lasă resursele cu hash să rămână în cache.

Măsoară din nou

După fiecare schimbare, verifică din nou cascada. Scopul nu este un scor perfect. Scopul este mai puține cereri critice, randare utilă mai devreme și mai puțină perturbare a firului principal.

Cum arată binele

O pagină sănătoasă nu are neapărat cel mai mic număr posibil de cereri. Are un traseu critic mic și deliberat.

Browserul primește HTML, CSS esențial, imaginea principală a conținutului dacă există una, poate un script mic necesar pentru navigație sau interacțiune în zona vizibilă inițial și setul minim de fonturi necesar pentru ca textul să fie lizibil. Tot restul își așteaptă rândul.

Aceasta este diferența dintre o pagină care este doar optimizată și o pagină care se simte rapidă.

Micșorarea fișierelor merită în continuare făcută. Dar dacă site-ul este deja comprimat rezonabil, următorul câștig de performanță nu este, de obicei, încă 2 KB economisiți dintr-un bundle. Este o cerere blocantă în minus, un fișier de font în minus, un script terț în minus, un lanț de dependențe în minus.

Mai puține cereri fac munca browserului mai simplă. Simplitatea este rapidă mai des decât ne place să recunoaștem.

Întrebări frecvente

Este un singur bundle mare mai bun decât multe fișiere mici?
Nu automat. Un bundle uriaș poate întârzia totul, mai ales la prima încărcare. Multe fișiere minuscule pot crea costuri de programare și execuție. Tiparul mai bun este să grupezi resursele care sunt mereu necesare împreună și să împarți după rută sau funcționalitate majoră.
Înseamnă HTTP/2 că numărul de cereri nu mai contează?
Nu. HTTP/2 reduce o parte din costul conexiunilor prin multiplexare și comprimarea headerelor, dar fiecare cerere are în continuare costuri de descoperire, prioritizare, server, cache, parsare și execuție.
Ar trebui să includ inline tot CSS-ul critic?
Includerea inline a unei cantități mici de CSS cu adevărat critic poate ajuta prima randare, dar prea mult inline face HTML-ul mai greu și mai dificil de cache-uit. Păstrează-l minim și măsoară efectul.
Care este cel mai ușor loc pentru reducerea cererilor?
Fonturile și scripturile terțe sunt adesea cele mai rapide câștiguri. Multe site-uri livrează greutăți de font nefolosite, analytics duplicat, pixeli vechi, widgeturi de chat sau embeduri care nu trebuie să se încarce imediat.
Câte cereri ar trebui să aibă o pagină?
Nu există o țintă universală. O pagină mică de conținut ar trebui să aibă foarte puține cereri critice. O aplicație complexă poate avea nevoie de mai multe. Concentrează-te pe reducerea cererilor înainte de prima randare și înainte de traseul principal de interacțiune.

Surse și lecturi suplimentare

  1. MDN Web Docs: HTTP caching
  2. web.dev: Optimize Largest Contentful Paint
  3. RFC 9113: HTTP/2
  4. HTTP Archive Web Almanac: Page Weight
Despre autor
The Wux Webtools Team

Ultima actualizare:

Continuă să citești