# Nuxt 4 en 2026: nueva estructura de directorios y migración desde Nuxt 3
> Guía completa de migración a Nuxt 4: estructura de directorios app/, capa singleton de obtención de datos, mejoras en TypeScript e instrucciones paso a paso con ejemplos de código.
- Published: 2026-05-01
- Updated: 2026-05-01
- Author: SharpSkill
- Tags: nuxt, vue, migración, typescript, tutorial
- Reading time: 8 min
---
Nuxt 4 introduce una estructura de directorios rediseñada que separa el código de la aplicación de la configuración, junto con una capa singleton de obtención de datos, reactividad superficial por defecto y contextos TypeScript divididos. Lanzado en julio de 2025 y actualmente en la versión 4.4, esta actualización mayor se enfoca en la evolución más que en la revolución, haciendo que la ruta de migración desde Nuxt 3 sea considerablemente más fluida que el salto de Nuxt 2 a 3.
> **Migración automatizada disponible**
>
> El equipo de Nuxt se asoció con Codemod para automatizar la mayoría de los pasos de migración. Basta con ejecutar `npx codemod@latest nuxt/4/migration-recipe` para gestionar la reestructuración de directorios, las actualizaciones de obtención de datos y los reemplazos de APIs obsoletas de forma automática.
## La nueva estructura del directorio app/ en Nuxt 4
Nuxt 4 traslada todo el código fuente de la aplicación a un directorio `app/` por defecto. Esta separación resuelve un problema real: los observadores de archivos en Linux y Windows funcionan significativamente mejor cuando el código de la aplicación reside en un subdirectorio dedicado en lugar de estar mezclado con `node_modules/`, `.git/` y archivos de configuración.
La nueva organización sigue esta estructura:
```text
my-nuxt-app/
├─ app/
│ ├─ assets/
│ ├─ components/
│ ├─ composables/
│ ├─ layouts/
│ ├─ middleware/
│ ├─ pages/
│ ├─ plugins/
│ ├─ utils/
│ ├─ app.vue
│ ├─ app.config.ts
│ └─ error.vue
├─ content/
├─ public/
├─ shared/ # Nuevo: código compartido entre app y servidor
├─ server/
└─ nuxt.config.ts
```
El directorio `shared/` es una adición notable. Cualquier composable o utilidad ubicado en `shared/` se auto-importa tanto en la aplicación Vue como en el servidor Nitro, eliminando la necesidad de importaciones manuales al compartir esquemas de validación, definiciones de tipos o funciones utilitarias entre ambos contextos.
## Migración paso a paso de Nuxt 3 a Nuxt 4
El proceso de actualización comienza con un solo comando. Nuxt detecta la estructura plana existente y continúa funcionando sin ningún cambio, por lo que la migración puede realizarse de forma incremental.
```bash
# Actualizar Nuxt y deduplicar dependencias
npx nuxt upgrade --dedupe
```
Después de actualizar el paquete, es necesario mover los archivos de la aplicación al directorio `app/`:
```bash
# Automatizar la reestructuración de directorios
npx codemod@latest nuxt/4/file-structure
```
Este codemod mueve `assets/`, `components/`, `composables/`, `layouts/`, `middleware/`, `pages/`, `plugins/`, `utils/`, `app.vue`, `error.vue` y `app.config.ts` dentro de `app/`. Los archivos que pertenecen a la raíz — `nuxt.config.ts`, `server/`, `public/` y `content/` — permanecen en su lugar.
Para proyectos que necesiten postergar la reestructuración, el directorio fuente puede configurarse explícitamente:
```typescript
// nuxt.config.ts
export default defineNuxtConfig({
srcDir: '.',
dir: { app: 'app' },
})
```
Esta configuración le indica a Nuxt 4 que resuelva los archivos desde la raíz del proyecto, replicando exactamente el comportamiento de Nuxt 3.
## Capa singleton de obtención de datos y claves reactivas
Nuxt 4 cambia fundamentalmente la forma en que `useAsyncData` y `useFetch` gestionan los datos. Múltiples componentes que llaman a la misma clave ahora comparten una única referencia reactiva en lugar de mantener copias independientes.
```typescript
// app/composables/useProductData.ts
export function useProductData(productId: string) {
return useAsyncData(
`product-${productId}`,
() => $fetch(`/api/products/${productId}`),
{
getCachedData: (key, nuxtApp, ctx) => {
// ctx.cause indica la razón del fetch
if (ctx.cause === 'refresh:manual') return undefined
return nuxtApp.payload.data[key]
},
},
)
}
```
Tres cambios destacan en esta nueva capa de datos:
- **Referencias compartidas**: llamar a `useProductData('abc')` en dos componentes devuelve las mismas refs `data`, `error` y `status`. Actualizar una actualiza ambas.
- **Limpieza automática**: cuando el último componente que usa una clave se desmonta, Nuxt libera los datos asociados de la memoria.
- **Claves reactivas**: envolver una clave en un computed o ref dispara automáticamente un nuevo fetch cuando el valor cambia.
El callback `getCachedData` ahora recibe un objeto de contexto con una propiedad `cause` (`'initial'`, `'refresh:hook'`, `'refresh:manual'` o `'watch'`), permitiendo un control granular sobre cuándo servir datos en caché versus obtener datos frescos.
> **Valores por defecto modificados**
>
> Las propiedades data y error de `useAsyncData`/`useFetch` ahora tienen `undefined` como valor por defecto en lugar de `null`. Es necesario actualizar las verificaciones `=== null` a `=== undefined` o utilizar una comparación no estricta.
## Reactividad superficial por defecto para mejor rendimiento
Nuxt 4 cambia `data` de `useAsyncData` y `useFetch` a `shallowRef` en lugar de `ref`. Vue ya no rastrea recursivamente cada propiedad anidada, lo que ofrece mejoras de rendimiento medibles para respuestas de API con objetos profundamente anidados o arrays grandes.
```typescript
// app/pages/dashboard.vue
```
Para la mayoría de las visualizaciones de solo lectura (dashboards, listados de productos, páginas de artículos), la reactividad superficial funciona sin ningún cambio de código. La opción `deep: true` sigue disponible para formularios o interfaces interactivas que mutan propiedades anidadas directamente.
## División de contextos TypeScript y seguridad de tipos mejorada
Nuxt 4 genera configuraciones TypeScript separadas para cada contexto del proyecto:
- `.nuxt/tsconfig.app.json` — Código de la aplicación Vue
- `.nuxt/tsconfig.server.json` — Código del servidor Nitro
- `.nuxt/tsconfig.shared.json` — Utilidades compartidas
- `.nuxt/tsconfig.node.json` — Configuración en tiempo de build
Esta separación significa que el IDE ya no sugiere APIs exclusivas del servidor en el código del cliente, y viceversa. Un único `tsconfig.json` en la raíz del proyecto referencia las cuatro configuraciones:
```json
{
"files": [],
"references": [
{ "path": "./.nuxt/tsconfig.app.json" },
{ "path": "./.nuxt/tsconfig.server.json" },
{ "path": "./.nuxt/tsconfig.shared.json" },
{ "path": "./.nuxt/tsconfig.node.json" }
]
}
```
La verificación de tipos en CI también cambia. El comando `vue-tsc` ahora requiere la bandera `-b` (modo build) para procesar correctamente las referencias de proyecto:
```bash
# Antes (Nuxt 3)
nuxt prepare && vue-tsc --noEmit
# Después (Nuxt 4)
nuxt prepare && vue-tsc -b --noEmit
```
Otro cambio en TypeScript: `compilerOptions.noUncheckedIndexedAccess` está activado por defecto (`true`). Acceder a un elemento de array o propiedad de objeto por índice ahora devuelve `T | undefined`, capturando errores potenciales en tiempo de ejecución durante la compilación.
## Nombres de componentes normalizados y Vue Router v5
Nuxt 4.3 realizó la actualización a Vue Router v5, eliminando la dependencia de `unplugin-vue-router`. Para la mayoría de las aplicaciones, esta actualización es transparente.
Las convenciones de nomenclatura de componentes están ahora estandarizadas. Un componente ubicado en `components/dashboard/MetricsCard.vue` obtiene el nombre `DashboardMetricsCard` de manera consistente en todos los contextos — incluyendo ``, Vue DevTools y utilidades de testing.
```vue
```
Los proyectos que utilizan `` con filtros de nombres de componentes deben actualizar los nombres para coincidir con esta nueva convención. El comportamiento anterior, donde el nombre podía variar según el contexto, ya no aplica.
## Gestión de cambios importantes en el manejo del head
Nuxt 4 incluye Unhead v2, que elimina varias propiedades obsoletas de `useHead` y `useSeoMeta`:
```typescript
// app/pages/product/[id].vue
```
Para proyectos que dependen de parámetros de template o el ordenamiento por alias, estas funcionalidades deben instalarse como plugins explícitos:
```typescript
// app/plugins/unhead.ts
import { TemplateParamsPlugin, AliasSortingPlugin } from '@unhead/vue/plugins'
export default defineNuxtPlugin({
setup() {
const unhead = injectHead()
unhead.use(TemplateParamsPlugin)
unhead.use(AliasSortingPlugin)
},
})
```
> **Línea de tiempo de soporte de Nuxt 3**
>
> Nuxt 3 continúa recibiendo actualizaciones de seguridad y correcciones de errores críticos hasta el 31 de julio de 2026. Después de esa fecha, Nuxt 3 dejará de tener soporte. Planificar la migración ahora evita ejecutar aplicaciones en producción sobre un framework sin mantenimiento.
## Lista de verificación de migración y errores comunes
El codemod automatizado gestiona la mayoría de los cambios, pero varios elementos requieren atención manual:
- **Eliminación de `window.__NUXT__`**: reemplazar con `useNuxtApp().payload`. Este objeto global se elimina después de la hidratación en Nuxt 4.
- **Hook `pages:extend`**: cambiar al nuevo hook `pages:resolved`, que se ejecuta después del escaneo de metadatos de páginas.
- **Booleano `dedupe`**: reemplazar `refresh({ dedupe: true })` con `refresh({ dedupe: 'cancel' })` y `false` con `'defer'`.
- **Estilos inline**: solo los estilos de componentes Vue se incluyen inline por defecto; el CSS global se carga como archivos separados. Agregar `features: { inlineStyles: true }` para restaurar el comportamiento de Nuxt 3.
- **`clearNuxtState`**: ahora restablece a los valores iniciales en lugar de `undefined`. Usar `clearNuxtState('key', { reset: false })` para el comportamiento anterior.
Una secuencia de migración práctica para aplicaciones en producción:
1. Ejecutar `npx nuxt upgrade --dedupe` y verificar que la aplicación compile correctamente
2. Ejecutar el codemod: `npx codemod@latest nuxt/4/migration-recipe`
3. Mover archivos a `app/` (automatizado por el codemod file-structure)
4. Actualizar las verificaciones de `null` a `undefined` en la lógica de obtención de datos
5. Probar los componentes `` con los nombres normalizados
6. Actualizar la verificación de tipos en CI para usar `vue-tsc -b --noEmit`
7. Ejecutar la suite completa de tests y corregir los errores de TypeScript expuestos por `noUncheckedIndexedAccess`
Para profundizar en los conceptos de Vue y Nuxt, es posible explorar las [preguntas de entrevista Vue/Nuxt](/technologies/vue-nuxt/interview-questions/nuxt-fundamentals) en SharpSkill, o revisar la [guía de SSR y generación estática](/blog/vue-nuxt/nuxt-3-ssr-static-generation) para obtener contexto sobre estrategias de renderizado que también aplican en Nuxt 4.
## Conclusión
- Nuxt 4.4 (versión actual a abril de 2026) estabiliza la estructura del directorio `app/`, la obtención de datos singleton y los contextos TypeScript divididos como valores predeterminados listos para producción
- El comando `npx codemod@latest nuxt/4/migration-recipe` automatiza la reestructuración de directorios, el reemplazo de APIs obsoletas y las actualizaciones de obtención de datos
- La reactividad superficial mediante `shallowRef` mejora el rendimiento de las páginas de solo lectura sin requerir cambios de código en la mayoría de los casos
- Las configuraciones TypeScript separadas por contexto (app, server, shared, node) eliminan las filtraciones de tipos entre contextos y mejoran el autocompletado del IDE
- Nuxt 3 alcanza su fin de vida el 31 de julio de 2026 — migrar antes de esa fecha garantiza que las aplicaciones funcionen sobre una versión soportada y mantenida activamente
- Vue Router v5 y Unhead v2 ofrecen APIs más limpias a costa de eliminar propiedades obsoletas que deben auditarse durante la migración
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/es/blog/vue-nuxt/nuxt-4-directory-structure-migration