Producción y entrega de aplicaciones React | Nicolás Garzón
Una aplicación React lista para producción necesita más que componentes correctos: build optimizado, configuración segura, observabilidad, compatibilidad y una estrategia de entrega coherente con su forma de renderizado.
El modo desarrollo prioriza feedback y diagnósticos:
Warnings.
Strict Mode.
Source maps amplios.
Fast Refresh.
Mensajes detallados.
El build de producción prioriza tamaño y ejecución:
El comando exacto depende del tooling. Generar archivos no equivale a desplegarlos ni operar un servidor.
Texto
Copiar src + dependencies
↓ bundler
optimized assets
↓ hosting / server
browser
HTML.
JavaScript chunks.
CSS.
Assets con hash.
Manifests.
Código de servidor cuando existe SSR o RSC.
No edites manualmente el output generado.
Minificar nombres y espacios.
Eliminar branches inaccesibles.
Combinar módulos.
Separar chunks.
Reescribir imports.
Estas optimizaciones dependen de módulos estáticos y paquetes correctamente publicados.
Tree shaking intenta excluir exports no utilizados. Puede fallar o ser limitado cuando:
El paquete tiene side effects globales.
Se usa CommonJS dinámico.
Las importaciones arrastran un entrypoint completo.
La librería no declara bien sus efectos.
No asumas que importar un único símbolo siempre produce un bundle mínimo. Verifica con bundle analysis.
Divide por rutas y features pesadas:
TypeScript
Copiar const AdminDashboard = lazy ( ( ) => import ( "./AdminDashboard" ) ) ;
Tamaño inicial.
Frecuencia de uso.
Prefetch.
Waterfalls.
Estados de fallback.
Errores de chunk.
Una estrategia demasiado fragmentada puede empeorar navegación y caché.
Formatos de imagen.
Dimensiones.
Responsive sources.
Fuentes.
Compresión.
Cache headers.
Carga diferida.
React no optimiza automáticamente cada asset.
Los assets con hash pueden recibir cache larga:
Texto
Copiar app.8f3a2.js → immutable
index.html → revalidation cortaUna CDN reduce latencia de archivos estáticos. SSR y APIs necesitan una estrategia distinta según región, caché y datos.
Todo valor incluido en el bundle cliente puede ser inspeccionado:
TypeScript
Copiar const apiUrl = import . meta. env. VITE_API_URL ; Un prefijo de “public” no protege secretos; indica que se expone al cliente.
Database credentials.
Private API keys.
Signing secrets.
Service tokens.
Mantén versiones compatibles y alineadas. Múltiples copias de React pueden producir invalid hook call y contextos separados.
Revisa lockfile, peer dependencies y deduplicación.
Define navegadores objetivo según producto. El bundler puede transformar sintaxis, pero no añade automáticamente todas las APIs faltantes.
Syntax transpilation.
Polyfills de APIs.
CSS support.
Runtime de React.
No cargues polyfills globales sin evaluar necesidad y coste.
Ayudan a relacionar errores minificados con source code. En producción decide:
Si se publican públicamente.
Si solo se suben al servicio de errores.
Qué información sensible contienen.
Cuánto aumentan el output.
Captura errores con contexto útil:
Versión de release.
Ruta.
Browser.
Component stack cuando exista.
Usuario o tenant con protección de privacidad.
Request correlation.
No envíes tokens, contraseñas ni payloads sensibles.
Los console.log dispersos no constituyen observabilidad. Define niveles y eventos relevantes.
Privacidad.
Volumen.
Sampling.
Offline behavior.
Errores de red.
Errores JavaScript.
Fallos de requests.
Web Vitals.
Latencia de navegación.
Chunk loading errors.
Hydration mismatches.
Conversiones o flujos críticos.
Uso por release.
Las métricas técnicas deben relacionarse con experiencia y producto.
Miden aspectos de carga, respuesta y estabilidad. Analiza percentiles y dispositivos, no solo promedios.
React puede influir mediante bundles, hydration y renders, pero imágenes, servidor y CSS también participan.
En aplicaciones SSR, monitorea mismatches y errores de hydration. Prueba:
Fechas y zonas horarias.
Datos aleatorios.
Browser-only APIs.
Extensiones.
HTML inválido.
Estado inicial.
No silencies warnings sin comprender la diferencia.
Permiten activar cambios gradualmente:
TypeScript
Copiar return flags. newCheckout ? < NewCheckout / > : < LegacyCheckout / > ;
Defaults seguros.
Ownership.
Expiración.
Telemetría.
Consistencia cliente-servidor.
Un flag permanente se convierte en deuda y ramas difíciles de probar.
Un release debe poder revertirse. Considera compatibilidad entre:
Bundle cliente cacheado.
API actual.
Migraciones de datos.
Service workers.
Server Actions o RSC payloads.
No despliegues cliente y backend asumiendo actualización instantánea de todos los usuarios.
Durante un despliegue puede coexistir:
Texto
Copiar old client + new server
new client + old serverDiseña APIs y datos para una ventana de compatibilidad. Evita eliminar campos inmediatamente cuando clientes cacheados todavía los usan.
Pipeline mínimo según proyecto:
Type checking.
Lint.
Unit/integration tests.
Build.
E2E de flujos críticos.
Accessibility checks.
Bundle budget.
Security scanning.
No toda aplicación necesita la misma cantidad de etapas, pero el build debe probarse antes del despliegue.
Inspecciona qué dependencias dominan el JavaScript. Pregunta:
¿Se usa en la ruta inicial?
¿Existe import más específico?
¿Puede cargarse bajo demanda?
¿Existe alternativa más pequeña?
¿El paquete duplica otra dependencia?
No cambies librerías únicamente por tamaño sin considerar mantenimiento y funcionalidad.
JavaScript inicial.
CSS.
Imágenes.
Requests.
Tiempo de interacción.
Route transitions.
Un budget convierte regresiones en señales visibles.
Lockfile versionado.
Actualizaciones revisadas.
Auditorías.
Provenance cuando esté disponible.
Paquetes mínimos.
Scripts de instalación bajo control.
No actualices automáticamente a producción sin tests.
Si la aplicación utiliza SSR o Server Components, producción también necesita:
Runtime compatible.
Escalado.
Timeouts.
Streaming.
Cache.
Observabilidad servidor.
Protección de secretos.
Manejo de regiones.
React no define toda esta operación; el framework y plataforma sí.
Una SPA puede publicarse como archivos estáticos, pero routing cliente necesita fallback al documento principal. Configura también:
Cache.
HTTPS.
Compression.
Headers de seguridad.
Error pages.
Asset paths.
Un service worker puede cachear assets y permitir offline, pero introduce versiones y actualización diferida.
No añadas uno por defecto. Define:
Qué se cachea.
Estrategia de actualización.
Cómo evitar servir HTML incompatible con chunks nuevos.
Experiencia offline.
Verifica con contenido y datos reales:
Longitud de textos.
Zoom.
Navegación teclado.
Errores de servidor.
Estados loading y empty.
Contraste final.
Focus tras navegación.
Un test de componente aislado no cubre toda la aplicación desplegada.
Build de producción exitoso.
React y React DOM compatibles.
Tests críticos aprobados.
Variables públicas revisadas.
Source maps configurados.
Monitoring vinculado a la release.
Assets comprimidos y cacheados.
Rutas y refresh directo probados.
Hydration sin warnings conocidos.
Accessibility smoke test.
Rollback disponible.
Confundir build con deployment.
Guardar secretos en variables cliente.
Medir solo en local y desktop potente.
Publicar source maps sensibles sin decisión.
Ignorar clientes cacheados durante cambios de API.
Desplegar sin observabilidad.
Añadir service worker sin estrategia de actualización.
Considerar que React optimiza imágenes, fuentes y caché automáticamente.
Producción incluye build, entrega, observabilidad y operación.
El output cliente siempre es inspeccionable.
Code splitting y tree shaking dependen del tooling y los paquetes.
Versiones cacheadas deben coexistir con el servidor.
SSR y RSC requieren runtime servidor.
Mide usuarios reales y prepara rollback.
¿Por qué una variable de entorno cliente no puede guardar secretos?
¿Qué diferencia existe entre tree shaking y code splitting?
¿Por qué old client y new server pueden coexistir?
¿Qué añade producción cuando existe SSR?
Ver respuestas
Porque su valor termina en archivos descargados por el navegador.
Tree shaking elimina exports no utilizados; code splitting separa código en chunks cargables.
Porque bundles y tabs pueden permanecer cacheados durante un despliegue.
Un runtime servidor con escalado, cache, timeouts, seguridad y observabilidad.
APIs avanzadas, legado y compatibilidad organiza qué capacidades son esenciales, especializadas, dependientes de versión o de framework.