Resumen ejecutivo
LCP mejorado
−620ms
2.84s → 2.22s (dashboard)
Bundle JS reducido
−31KB
231 KB → 200 KB gzip
API p95 mejorado
−87ms
GET /patients: 312 → 225ms
Build frío
+4s
38s → 42s (WebP plugin overhead)
Peso total de página
−1.4MB
3.1 MB → 1.7 MB (dashboard)
Core Web Vitals — Antes vs Después
Métricas de página · Staging Chrome 124 · Cable
baseline: main@a3f1c92 · after: feat/optimize-dashboard@b8d20e5| Métrica / URL | Antes | Después | Delta | Target | Veredicto |
|---|---|---|---|---|---|
|
LCP —
/ landingLargest Contentful Paint
|
1.42s | 1.31s | −110ms | < 2.5s | ✓ MEJOR |
|
LCP —
/dashboardLargest Contentful Paint
|
2.84s | 2.22s | −620ms | < 2.5s | ✓ MEJOR |
|
FCP —
/dashboardFirst Contentful Paint
|
1.61s | 1.43s | −180ms | < 1.8s | ✓ MEJOR |
|
CLS —
/patientsCumulative Layout Shift
|
0.07 | 0.03 | −0.04 | < 0.1 | ✓ MEJOR |
|
INP —
/dashboardInteraction to Next Paint
|
168ms | 152ms | −16ms | < 200ms | ● OK |
|
TTFB —
/dashboardTime to First Byte
|
620ms | 610ms | −10ms | < 800ms | ● OK |
|
Bundle JS (gzip)
Tamaño total de scripts
|
231 KB | 200 KB | −31 KB | < 200 KB | ● OK |
|
Peso total de página
/dashboard — todos los recursos
|
3.1 MB | 1.7 MB | −1.4 MB | < 1 MB | ⚠ WARN |
|
Recursos bloqueantes
Scripts / CSS render-blocking
|
3 | 3 | 0 | 0 | ✗ FAIL |
Puntuación Lighthouse (estimada)
/ — Landing
84
Performance
/dashboard — Antes
60
Performance
/dashboard — Después
80
Performance ▲20
/patients — Después
90
Performance
API Latency (100 req × 10 conc.)
Railway · us-east-1| Endpoint | p50 | p95 | p99 | SLA |
|---|---|---|---|---|
|
GET /api/patients
Antes → Después
|
118 → 112ms | 312 → 225ms | 480 → 390ms | OK |
|
GET /api/sessions/latest
Antes → Después
|
89 → 84ms | 190 → 181ms | 310 → 295ms | ✓ OK |
|
POST /api/reports/generate
async PDF — sin cambios
|
2.1s | 4.8s | 7.2s | ⚠ SLOW |
Build Performance
MacBook M2 Pro · Node 20| Tarea | Antes | Después | Δ |
|---|---|---|---|
| Cold build (next build) | 38.2s | 42.1s | +3.9s |
| HMR (hot reload) | 340ms | 355ms | +15ms |
| Test suite (vitest) | 12.4s | 12.6s | +0.2s |
| TypeScript check | 8.1s | 8.1s | 0 |
| ESLint | 4.3s | 4.3s | 0 |
Desglose de peso de página — /dashboard
Cambios clave del PR
b8d20e5
feat(dashboard): migrate img→Next.js Image + WebP + lazy list sessions
app/dashboard/PatientCard.tsx
- <img src={patient.avatar} alt={patient.name} width={64} height={64} />
+ <Image src={patient.avatar} alt={patient.name} width={64} height={64}
+ format="webp" quality={80} loading="lazy" placeholder="blur" />
app/dashboard/SessionList.tsx
- const sessions = await fetchAllSessions(patientId) // 300+ items
+ const sessions = await fetchSessions(patientId, { limit: 20, page: 1 })
+ // Infinite scroll via IntersectionObserver — carga rest on demand
next.config.js
images: {
+ formats: ['image/avif', 'image/webp'],
+ minimumCacheTTL: 86400,
}
Recomendaciones post-PR
✓ APROBADO para merge
7 de 9 métricas mejoran. LCP del dashboard pasa de 2.84s a 2.22s, cumpliendo el target de <2.5s. Bundle JS toca el límite de 200 KB.
⚠ INVESTIGAR — Build time
El overhead del plugin WebP añade +3.9s al cold build (38s → 42s). Considerar cache de imágenes en CI o migrar a sharp en modo incremental.
✗ BLOQUEANTE — Scripts 3rd-party
3 recursos render-blocking siguen activos (Intercom + Segment + fuente externa). Abrir ticket separado para defer/async. Target: 0 bloqueantes.
SIGUIENTE — /api/reports lento
POST /reports/generate supera SLA con p95 de 4.8s. Candidato para cola de tareas (Celery/BullMQ) + notificación push al dietista.