codigo0/docs/SOLUCION_DEFINITIVA_USELAYOUTEFFECT.md

220 lines
5.8 KiB
Markdown
Raw Normal View History

# 🔧 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:
1. **`hast-util-to-jsx-runtime`** (dependencia de `react-markdown`) usa React pero estaba siendo clasificado como `vendor-utils`
2. **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
3. **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:**
```typescript
// 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`)
```typescript
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`)
```typescript
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
```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`)
```typescript
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
```bash
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
```bash
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
1. **Abrir DevTools > Network**
2. **Recargar la página**
3. **Verificar orden de carga:**
- `vendor-react-*.js` debe cargarse PRIMERO
- Luego `vendor-utils-*.js` y `vendor-markdown-*.js`
- NO debe aparecer `vendor-other-*.js`
4. **Verificar en Console:**
- NO debe aparecer el error `useLayoutEffect`
- NO debe haber warnings sobre React duplicado
## 🔍 Troubleshooting
### Si el error persiste
1. **Limpiar completamente:**
```bash
rm -rf node_modules package-lock.json dist
npm install
npm run build
```
2. **Verificar que no hay React duplicado:**
```bash
npm ls react react-dom
```
Debe mostrar solo una versión de cada uno.
3. **Verificar chunks generados:**
```bash
ls -la dist/assets/ | grep vendor
```
NO debe aparecer `vendor-other`.
4. **Limpiar caché del navegador:**
- Ver `docs/LIMPIAR_CACHE_NAVEGADOR.md`
### Si el build falla
1. **Revisar logs:**
```bash
npm run build 2>&1 | grep -i "error\|unclassified"
```
2. **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`
## 📋 Checklist Pre-Deploy
- [ ] `npm run build` pasa sin errores
- [ ] `node scripts/diagnose-react.js` muestra todo ✅
- [ ] `node scripts/verify-build.js` pasa
- [ ] NO se genera `vendor-other`
- [ ] `vendor-react` se carga primero (verificar en Network tab)
- [ ] No hay errores `useLayoutEffect` en 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
1. `vite.config.ts`
- Alias explícitos de React
- Clasificación de `hast-util-to-jsx-runtime` en `vendor-react`
- `optimizeDeps` mejorado
- Orden de carga de chunks
2. `package.json`
- Añadido `overrides` para React
3. `scripts/diagnose-react.js` (nuevo)
- Script de diagnóstico
4. `scripts/verify-build.js` (mejorado)
- Verificación post-build
## 🔗 Referencias
- [Vite: Dependency Pre-bundling](https://vitejs.dev/guide/dep-pre-bundling.html)
- [Vite: Build Options](https://vitejs.dev/config/build-options.html)
- [React: Multiple Versions](https://react.dev/learn/start-a-new-react-project#can-i-use-react-without-a-framework)