tehnic9 min citire

Performanța aplicațiilor web: principii pe care nu le predă nimeni

Timpi de încărcare, bundle sizes, Core Web Vitals — sunt indicatori, nu obiective. Înțelegerea cauzelor reale ale performanței slabe și a modului corect de a le măsura este jumătate din bătălie.

Echipa AAC·

Cel mai mare mit al optimizării de performanță

Migrezi pe un CDN mai rapid, reduci dimensiunea imaginilor și adaugi lazy loading. Site-ul tot e lent. Ce s-a întâmplat?

Probabil ai rezolvat problemele vizibile, nu problemele reale. Optimizarea fără măsurare precisă este ghicire mascată în inginerie.

Nivelele performanței: o ierarhie pe care trebuie să o înțelegi

Performanța are straturi. O optimizare la nivel greșit nu ajută (sau face lucrurile mai rele):

1. Algoritmul — O complexitate O(n²) nu devine O(n) adăugând un cache.

2. Baza de date — Un query fără index care face table scan pe 10 milioane de rânduri nu se rezolvă cu Redis în față.

3. Arhitectura de rețea — N+1 query-uri cu 200ms latency fiecare = 20 secunde pentru 100 items.

4. Randarea — Bundle de 3MB care blochează main thread-ul înainte de a arăta ceva.

5. Caching — Ineficient, dar abia la final. Nu caching-ul salvează o arhitectură greșită.

Cum să măsori corect

Instrumentele gratuite (Lighthouse, WebPageTest) sunt excelente, dar au limite: măsoară experiența sintetică, nu pe utilizatorul real.

Ce să adaugi obligatoriu:

  • Real User Monitoring (RUM): Google CrUX sau un tool ca Datadog RUM pentru a vedea p75/p95 pe utilizatorii reali
  • Database query profiling: EXPLAIN ANALYZE în PostgreSQL, slow query log în MySQL
  • Backend tracing: OpenTelemetry + Jaeger/Zipkin pentru a vedea unde se pierde timpul în request-uri
  • Frontend profiling: React Profiler pentru componente, Chrome DevTools Performance tab pentru runtime

Cazul clasic: N+1 queries

Cel mai frecvent bottleneck în aplicații cu ORM:

GET /api/orders
→ SELECT * FROM orders (1 query, 200ms)
→ FOR EACH order: SELECT * FROM users WHERE id = ? (100 queries × 50ms = 5 secunde)
Total: 5.2 secunde pentru 100 comenzi

Soluția: eager loading sau un JOIN corect reduce asta la 250ms.

Lessonul: niciun cache nu ajută dacă nu găsești N+1 mai întâi.

Core Web Vitals: ce contează cu adevărat

  • LCP (Largest Contentful Paint): Optimizezi imaginea hero sau fontul care blochează render-ul
  • INP (Interaction to Next Paint): Identifici handlere de click care fac muncă sincronă pe main thread
  • CLS (Cumulative Layout Shift): Rezervi spațiu explicit pentru elemente care se încarcă async

Nu optimiza LCP dacă INP este 800ms — utilizatorul simte interactivitatea mai mult decât viteza de încărcare.

Priorități greșite frecvente

❌ Minifici CSS când problema e un query de 3 secunde ❌ Adaugi CDN când problema e logică de business sincronă pe server ❌ Optimizezi frontend când problema e API-ul care face 20 de calluri externe

Concluzie

Performanța bună este rezultatul deciziilor de arhitectură corecte luate de la început, nu al patch-urilor aplicate la final. Cele mai eficiente optimizări le facem la nivelul logicii și al bazei de date — nu la nivel de compilator CSS.

Dacă ai o aplicație lentă și nu știi de unde să începi, un audit de performanță de 1-2 săptămâni este cel mai scurt drum spre claritate.

performanțăweboptimizarebaze de datefrontend

Vrei să discutăm despre proiectul tău?

Aplicăm aceste principii în fiecare proiect.

Contactează-ne