¿Qué es Nuxt?
Nuxt es el meta-framework de Vue. Mientras que Vue te proporciona componentes y reactividad, Nuxt añade las piezas que toda aplicación real necesita —enrutamiento, renderizado en el servidor, obtención de datos, un entorno de ejecución de servidor y un ecosistema de módulos— y las integra todas con configuraciones predeterminadas coherentes.
Es la contraparte de Next.js para Vue y sigue la misma filosofía general: utilizar el sistema de archivos para el enrutamiento, renderizar en el servidor por defecto y tratar la obtención de datos como una prioridad fundamental. Si ya conoces Vue, Nuxt se siente como un paso siguiente natural en lugar de un framework nuevo.
Enrutamiento basado en archivos
Los archivos en pages/ se convierten en rutas. Los segmentos dinámicos utilizan corchetes y las carpetas anidadas crean rutas anidadas.
pages/
├── index.vue # /
├── about.vue # /about
├── blog/
│ ├── index.vue # /blog
│ └── [slug].vue # /blog/:slug
└── dashboard/
├── index.vue # /dashboard
└── settings.vue # /dashboard/settings
<!-- pages/blog/[slug].vue -->
<script setup>
const route = useRoute();
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`);
</script>
<template>
<article>
<h1>{{ post.title }}</h1>
<div v-html="post.body" />
</article>
</template>
useRoute te proporciona la ruta actual, y NuxtLink gestiona la navegación del lado del cliente con prefetching. Los layouts en layouts/ envuelven las páginas y te permiten compartir una estructura común entre múltiples rutas.
Auto-imports
Nuxt importa automáticamente las APIs de Vue, sus propios composables, y tus componentes y composables. Así escribes menos código repetitivo y los archivos se mantienen enfocados.
<!-- components/UserCard.vue -->
<script setup>
const props = defineProps({ user: Object });
</script>
<template>
<article class="card">
<h3>{{ user.name }}</h3>
</article>
</template>
Los componentes en components/ están disponibles en cualquier lugar sin necesidad de importarlos, y tus propios composables en composables/ también se importan automáticamente. El resultado es menos ceremonia y menos listas de imports que mantener.
Obtención de datos con useFetch
useFetch y useAsyncData son la forma recomendada de cargar datos. Se ejecutan durante el renderizado en el servidor, transfieren el resultado al cliente y exponen el estado de carga y de error.
<!-- pages/posts.vue -->
<script setup>
const { data: posts, pending, error } = await useFetch("/api/posts");
</script>
<template>
<p v-if="pending">Loading…</p>
<p v-else-if="error">Could not load posts.</p>
<PostList v-else :posts="posts" />
</template>
Debido a que la solicitud ocurre en el servidor, el primer renderizado ya incluye los datos. Esto evita el destello de contenido vacío que ocurre al realizar la obtención de datos en onMounted, y funciona con almacenamiento en caché, revalidación y claves personalizadas para un control más preciso.
El servidor Nitro
Nuxt incluye un motor de servidor llamado Nitro. Los archivos en server/api/ se convierten en endpoints de API, y server/routes/ puede servir handlers personalizados.
// server/api/users.get.ts
export default defineEventHandler(async () => {
const config = useRuntimeConfig();
return $fetch("https://api.example.com/users", {
headers: { Authorization: config.apiKey },
});
});
// server/api/users.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event);
const user = await db.user.create({ data: body });
return { user };
});
Esto mantiene los secretos y las credenciales de terceros en el servidor. El cliente llama a tu propio endpoint y Nitro se encarga del resto. El mismo motor se despliega en Node, funciones serverless, edge runtimes y hosts estáticos a través de adaptadores.
SEO, meta y módulos
Nuxt simplifica el SEO optimizado para el servidor mediante el uso de composables.
<!-- pages/about.vue -->
<script setup>
useSeoMeta({
title: "About us",
description: "Who we are and what we build.",
ogImage: "/og/about.png",
});
</script>
Los composables useHead y useSeoMeta gestionan los títulos, descripciones, URLs canónicas y etiquetas sociales, y se renderizan correctamente en el servidor para que los rastreadores puedan verlos. Más allá de esto, el ecosistema de módulos de Nuxt añade autenticación, contenido, imágenes, analíticas y más con solo una o dos líneas de configuración.
Modos de renderizado
Nuxt soporta diversas estrategias de renderizado y te permite elegir una por ruta:
- Universal (SSR) renderiza en el servidor e hidrata en el cliente; es la opción por defecto.
- Static (SSG) prerenderiza las páginas en el momento del build.
- SPA renderiza completamente en el cliente, como una aplicación de Vue clásica.
- Hybrid combina estas estrategias, permitiendo que las páginas de marketing sean estáticas mientras que un dashboard se renderice en el cliente.
También puedes habilitar la regeneración estática incremental y reglas de ruta para ajustar el almacenamiento en caché y el renderizado sin necesidad de reestructurar la aplicación.
Mejores prácticas
- Usa
useFetchyuseAsyncDataen lugar de realizar peticiones enonMounted. - Mantén los secretos y las llamadas a terceros en rutas
server/api. - Deja que los auto-imports hagan su trabajo; no luches contra ellos con importaciones manuales.
- Define los metadatos de SEO con
useSeoMetaen cada página. - Elige un modo de renderizado por ruta en lugar de un único modo para todo.
- Usa
NuxtLinkpara la navegación interna para que el prefetching y las transiciones funcionen. - Organiza la lógica reutilizable en composables dentro de
composables/.
Errores comunes
- Realizar el fetch de datos en
onMountedy perder el beneficio de SSR. - Exponer API keys al llamar a terceros directamente desde el cliente.
- Recurrir a un store global cuando
useStateo un composable serían suficientes. - Ignorar las reglas de rutas y renderizar en exceso páginas que podrían ser estáticas.
- Asumir que las API de los módulos de Nuxt 2 funcionan sin cambios en Nuxt 3.
- Omitir los metadatos de SEO porque el framework hace que sea fácil olvidarlos.
Próximos pasos
Nuxt convierte Vue en una plataforma full-stack. Profundiza tus conocimientos de Vue, añade TypeScript y compara este enfoque con Next.js y SvelteKit. Después, construye una aplicación pequeña con una página, una ruta de servidor y useFetch para experimentar lo natural que encajan todas las piezas.