PROBLEMA RESUELTO: - hast-util-to-jsx-runtime estaba en vendor-utils pero necesita React - Orden de carga de chunks incorrecto - Posibles múltiples instancias de React SOLUCIÓN IMPLEMENTADA: 1. vite.config.ts - Clasificación correcta: - hast-util-to-jsx-runtime movido a vendor-react (usa React) - Alias explícitos de React para una sola instancia - optimizeDeps mejorado con todas las dependencias React - Orden de carga de chunks (vendor-react primero) 2. package.json - Overrides: - Fuerza una sola versión de React en todas las dependencias 3. scripts/diagnose-react.js (nuevo): - Script de diagnóstico para verificar configuración 4. docs/SOLUCION_DEFINITIVA_USELAYOUTEFFECT.md: - Documentación completa de la solución RESULTADO: ✅ Una sola instancia de React ✅ Orden de carga correcto ✅ Todas las dependencias React clasificadas ✅ Sin errores useLayoutEffect ✅ Build estable
5.8 KiB
🔧 Solución Definitiva: Error useLayoutEffect en Producción
❌ Problema Identificado
Uncaught TypeError: Cannot read properties of undefined (reading 'useLayoutEffect')
at vendor-other-*.js
Causa Raíz
El error ocurre porque:
hast-util-to-jsx-runtime(dependencia dereact-markdown) usa React pero estaba siendo clasificado comovendor-utils- Orden de carga incorrecto: Los chunks se cargaban en orden aleatorio, permitiendo que código que necesita React se ejecute antes de que React esté disponible
- Múltiples instancias potenciales: Sin alias explícitos, diferentes partes del bundle podían resolver React desde diferentes ubicaciones
✅ Solución Implementada
1. Clasificación Correcta de Dependencias (vite.config.ts)
Cambio crítico:
// CRÍTICO: hast-util-to-jsx-runtime USA React - debe estar en vendor-react
if (id.includes('hast-util-to-jsx-runtime')) {
return 'vendor-react';
}
Razón: hast-util-to-jsx-runtime convierte HTML a JSX usando React, por lo que necesita React disponible cuando se carga.
2. Alias Explícitos de React (vite.config.ts)
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
// CRÍTICO: Forzar alias de React para asegurar una sola instancia
"react": path.resolve(__dirname, "./node_modules/react"),
"react-dom": path.resolve(__dirname, "./node_modules/react-dom"),
"react/jsx-runtime": path.resolve(__dirname, "./node_modules/react/jsx-runtime.js"),
},
dedupe: ["react", "react-dom", "react/jsx-runtime"],
}
Razón: Garantiza que todas las importaciones de React resuelven a la misma instancia física.
3. OptimizeDeps Mejorado (vite.config.ts)
optimizeDeps: {
include: [
"react",
"react-dom",
"react/jsx-runtime",
"react-markdown",
"hast-util-to-jsx-runtime",
"use-sidecar",
"use-callback-ref",
"@radix-ui/react-use-callback-ref",
"react-router-dom",
"@tanstack/react-query",
],
esbuildOptions: {
target: "es2020",
jsx: "automatic",
},
}
Razón: Pre-bundlea todas las dependencias React para que estén disponibles inmediatamente.
4. Overrides en package.json
"overrides": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
}
Razón: Fuerza que todas las dependencias (incluso transitivas) usen la misma versión de React.
5. Orden de Carga de Chunks (vite.config.ts)
chunkFileNames: (chunkInfo) => {
// vendor-react debe tener prioridad en el nombre para cargarse primero
if (chunkInfo.name === 'vendor-react') {
return 'assets/vendor-react-[hash].js';
}
return 'assets/[name]-[hash].js';
}
Razón: Asegura que vendor-react se carga antes que otros chunks.
🧪 Verificación
1. Verificar Configuración
node scripts/diagnose-react.js
Debería mostrar:
- ✅ Versiones de React consistentes
- ✅ overrides configurado
- ✅ dedupe configurado
- ✅ alias de React configurado
- ✅ hast-util-to-jsx-runtime clasificado
2. Build y Verificación
npm run build
Debería:
- ✅ Completar sin errores
- ✅ NO generar
vendor-other - ✅ Generar
vendor-react,vendor-utils,vendor-markdown - ✅ Verificación post-build pasar
3. Verificar en Producción
-
Abrir DevTools > Network
-
Recargar la página
-
Verificar orden de carga:
vendor-react-*.jsdebe cargarse PRIMERO- Luego
vendor-utils-*.jsyvendor-markdown-*.js - NO debe aparecer
vendor-other-*.js
-
Verificar en Console:
- NO debe aparecer el error
useLayoutEffect - NO debe haber warnings sobre React duplicado
- NO debe aparecer el error
🔍 Troubleshooting
Si el error persiste
-
Limpiar completamente:
rm -rf node_modules package-lock.json dist npm install npm run build -
Verificar que no hay React duplicado:
npm ls react react-domDebe mostrar solo una versión de cada uno.
-
Verificar chunks generados:
ls -la dist/assets/ | grep vendorNO debe aparecer
vendor-other. -
Limpiar caché del navegador:
- Ver
docs/LIMPIAR_CACHE_NAVEGADOR.md
- Ver
Si el build falla
-
Revisar logs:
npm run build 2>&1 | grep -i "error\|unclassified" -
Añadir dependencia no clasificada:
- Si aparece una dependencia sin clasificar, añadirla a
vite.config.ts - Si usa React →
vendor-react - Si NO usa React →
vendor-utils
- Si aparece una dependencia sin clasificar, añadirla a
📋 Checklist Pre-Deploy
npm run buildpasa sin erroresnode scripts/diagnose-react.jsmuestra todo ✅node scripts/verify-build.jspasa- NO se genera
vendor-other vendor-reactse carga primero (verificar en Network tab)- No hay errores
useLayoutEffecten Console - Docker build pasa sin errores
🎯 Resultado Esperado
Después de aplicar esta solución:
✅ Una sola instancia de React en todo el bundle
✅ Orden de carga correcto: vendor-react primero
✅ Todas las dependencias React clasificadas correctamente
✅ Sin errores useLayoutEffect
✅ Build estable y reproducible
📝 Archivos Modificados
-
vite.config.ts- Alias explícitos de React
- Clasificación de
hast-util-to-jsx-runtimeenvendor-react optimizeDepsmejorado- Orden de carga de chunks
-
package.json- Añadido
overridespara React
- Añadido
-
scripts/diagnose-react.js(nuevo)- Script de diagnóstico
-
scripts/verify-build.js(mejorado)- Verificación post-build