Migrar desde Next.js
Aquí hay algunos conceptos clave y estrategias de migración para ayudarte a empezar. ¡Usa el resto de nuestra documentación y nuestra comunidad de Discord para seguir adelante!
Similitudes clave entre Next.js y Astro
Sección titulada “Similitudes clave entre Next.js y Astro”Next.js y Astro comparten algunas similitudes que te ayudarán a migrar tu proyecto:
- La sintaxis de los archivos
.astroes similar a JSX. Escribir Astro debería resultarte familiar. - Los proyectos de Astro también pueden ser SSG o SSR con pre-renderizado a nivel de página.
- Astro usa enrutamiento basado en archivos, y permite que páginas con nombres especiales creen rutas dinámicas.
- Astro está basado en componentes, y tu estructura de markup será similar antes y después de tu migración.
- Astro tiene integraciones oficiales para React, Preact, y Solid para que puedas usar tus componentes JSX existentes. Ten en cuenta que en Astro, estos archivos deben tener una extensión
.jsxo.tsx. - Astro tiene soporte para instalar paquetes NPM, incluyendo librerías de React. Muchas de tus dependencias existentes funcionarán en Astro.
Diferencias clave entre Next.js y Astro
Sección titulada “Diferencias clave entre Next.js y Astro”Cuando reconstruyas tu sitio de Next.js en Astro, notarás algunas diferencias importantes:
-
Next.js es una single-page app de React, y usa
index.jscomo raíz de tu proyecto. Astro es un sitio multi-página, eindex.astroes tu página de inicio. -
Los componentes
.astrono se escriben como funciones exportadas que devuelven plantillas de página. En su lugar, dividirás tu código en un “code fence” para tu JavaScript y un body exclusivamente para el HTML que generas. -
orientado a contenido: Astro fue diseñado para mostrar tu contenido y permitirte optar por la interactividad solo cuando sea necesario. Una app existente de Next.js podría estar construida para alta interactividad del lado del cliente y puede requerir técnicas avanzadas de Astro para incluir elementos que son más difíciles de replicar usando componentes
.astro, como dashboards.
Convierte tu proyecto de Next.js
Sección titulada “Convierte tu proyecto de Next.js”Cada migración de proyecto será diferente, pero hay algunas acciones comunes que realizarás al convertir de Next.js a Astro.
Crea un nuevo proyecto de Astro
Sección titulada “Crea un nuevo proyecto de Astro”Usa el comando create astro de tu gestor de paquetes para lanzar el asistente CLI de Astro o elige un tema de la comunidad del Astro Theme Showcase.
Puedes pasar un argumento --template al comando create astro para iniciar un nuevo proyecto de Astro con uno de nuestros starters oficiales (p. ej. docs, blog, portfolio). O, puedes iniciar un nuevo proyecto desde cualquier repositorio existente de Astro en GitHub.
# launch the Astro CLI Wizardnpm create astro@latest
# create a new project with an official examplenpm create astro@latest -- --template <example-name># launch the Astro CLI Wizardpnpm create astro@latest
# create a new project with an official examplepnpm create astro@latest --template <example-name># launch the Astro CLI Wizardyarn create astro@latest
# create a new project with an official exampleyarn create astro@latest --template <example-name>Luego, copia los archivos existentes de tu proyecto de Next a tu nuevo proyecto de Astro en una carpeta separada fuera de src.
Visita https://astro.new para la lista completa de plantillas oficiales de inicio, y enlaces para abrir un nuevo proyecto en StackBlitz o CodeSandbox.
Instalar integraciones (opcional)
Sección titulada “Instalar integraciones (opcional)”Puede que te resulte útil instalar algunas de las integraciones opcionales de Astro para usar mientras conviertes tu proyecto de Next a Astro:
-
@astrojs/react: para reutilizar algunos componentes de UI de React existentes en tu nuevo sitio de Astro, o seguir escribiendo con componentes de React.
-
@astrojs/mdx: para traer archivos MDX existentes de tu proyecto de Next, o para usar MDX en tu nuevo sitio de Astro.
Pon tu código fuente en src
Sección titulada “Pon tu código fuente en src”Siguiendo la estructura de proyecto de Astro:
-
Mantén la carpeta
public/de Next sin cambios.Astro usa el directorio
public/para assets estáticos, al igual que Next. No se necesita ningún cambio en esta carpeta ni en su contenido. -
Copia o mueve otros archivos y carpetas de Next (p. ej.
pages,stylesetc.) a la carpetasrc/de Astro mientras reconstruyes tu sitio, siguiendo la estructura de proyecto de Astro.Como Next, la carpeta
src/pages/de Astro es una carpeta especial usada para enrutamiento basado en archivos. Todas las demás carpetas son opcionales, y puedes organizar el contenido de tu carpetasrc/como quieras. Otras carpetas comunes en proyectos de Astro incluyensrc/layouts/,src/components,src/styles,src/scripts.
El archivo de configuración de Astro
Sección titulada “El archivo de configuración de Astro”Astro tiene un archivo de configuración en la raíz de tu proyecto llamado astro.config.mjs. Este se usa únicamente para configurar tu proyecto de Astro y cualquier integración instalada, incluyendo adaptadores SSR.
Tips: Convertir archivos JSX a archivos .astro
Sección titulada “Tips: Convertir archivos JSX a archivos .astro”Aquí hay algunos tips para convertir un componente .js de Next en un componente .astro:
-
Usa el JSX devuelto de la función del componente existente de Next.js como base para tu plantilla HTML.
-
Cambia cualquier sintaxis de Next o JSX a sintaxis de Astro o a estándares web de HTML. Esto incluye
<Link>,<Script>,{children}, yclassName, por ejemplo. -
Mueve cualquier JavaScript necesario, incluyendo declaraciones de importación, a un “code fence” (
---). Nota: JavaScript para renderizar contenido condicionalmente a menudo se escribe directamente dentro de la plantilla HTML en Astro. -
Usa
Astro.propspara acceder a cualquier prop adicional que se pasara previamente a tu función de Next. -
Decide si algún componente importado también necesita convertirse a Astro. Con la integración oficial instalada, puedes usar componentes de React existentes en tu archivo de Astro. Pero, puede que quieras convertirlos a componentes
.astro, ¡especialmente si no necesitan ser interactivos! -
Reemplaza
getStaticProps()con declaraciones import oimport.meta.glob()para consultar tus archivos locales. Usafetch()para obtener datos externos.
Ve un ejemplo de un archivo .js de Next convertido paso a paso.
Comparación: JSX vs Astro
Sección titulada “Comparación: JSX vs Astro”Compara el siguiente componente de Next y un componente de Astro correspondiente:
import Header from "./header";import Footer from "./footer";import "./layout.css";
export async function getStaticProps() { const res = await fetch("https://api.github.com/repos/withastro/astro"); const json = await res.json(); return { props: { message: json.message, stars: json.stargazers_count || 0 }, }}
const Component = ({ stars, message }) => {
return ( <> <Header /> <p style={{ backgroundColor: `#f4f4f4`, padding: `1em 1.5em`, textAlign: `center`, marginBottom: `1em` }}>Astro has {stars} 🧑🚀</p> <Footer /> </> )}
export default Component;---import Header from "./header";import Footer from "./footer";import "./layout.css";
const res = await fetch("https://api.github.com/repos/withastro/astro");const json = await res.json();const message = json.message;const stars = json.stargazers_count || 0;---<Header /><p class="banner">Astro has {stars} 🧑🚀</p><Footer />
<style> .banner { background-color: #f4f4f4; padding: 1em 1.5em; text-align: center; margin-bottom: 1em; }</style>Migrar archivos de layout
Sección titulada “Migrar archivos de layout”Puede que te resulte útil comenzar convirtiendo tus layouts y plantillas de Next.js en componentes de layout de Astro.
Next tiene dos métodos diferentes para crear archivos de layout, cada uno de los cuales maneja los layouts de manera diferente a Astro:
-
El directorio
pages
Cada página de Astro requiere explícitamente que las etiquetas <html>, <head>, y <body> estén presentes, así que es común reutilizar un archivo de layout entre páginas. Astro usa un <slot /> para el contenido de la página, sin necesidad de declaración de import. Ten en cuenta las plantillas HTML estándar, y el acceso directo a <head>:
------<html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width" /> <meta name="generator" content={Astro.generator} /> <title>Astro</title> </head> <body> <!-- Wrap the slot element with your existing layout templating --> <slot /> </body></html>Migrar desde el directorio pages de Next.js
Sección titulada “Migrar desde el directorio pages de Next.js”Tu proyecto de Next puede tener un archivo pages/_document.jsx que importa componentes de React para personalizar el <head> de tu app:
import Document, { Html, Head, Main, NextScript } from "next/document";
export default class MyDocument extends Document { render() { return ( <Html lang="en"> <Head> <link rel="icon" href="/favicon.ico" /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); }}-
Crea un nuevo archivo de layout de Astro usando solo el JSX devuelto.
-
Reemplaza cualquier componente de React con etiquetas
<html>,<head>,<slot>, y otras etiquetas estándar de HTML.src/layouts/Document.astro <html lang="en"><head><link rel="icon" href="/favicon.ico" /></head><body><slot/></body></html>
Migrar desde el directorio /app de Next.js
Sección titulada “Migrar desde el directorio /app de Next.js”Los archivos de layout del directorio app/ de Next.js se crean con dos archivos: un archivo layout.jsx para personalizar los contenidos de <html> y <body>, y un archivo head.jsx para personalizar los contenidos del elemento <head>.
export default function Layout({ children }) { return ( <html lang="en"> <body>{children}</body> </html> );}export default function Head() { return ( <> <title>My Page</title> </> );}-
Crea un nuevo archivo de layout de Astro usando solo el JSX devuelto.
-
Reemplaza ambos archivos con un único archivo de layout de Astro que contenga un page shell (etiquetas
<html>,<head>, y<body>) y un<slot/>en lugar de la prop{children}de React:src/layouts/Layout.astro <html lang="en"><head><title>My Page</title></head><body><slot/></body></html>
Migrar páginas y posts
Sección titulada “Migrar páginas y posts”En Next.js, tus posts viven en /pages o en /app/routeName/page.jsx.
En Astro, todo el contenido de tus páginas debe vivir dentro de src/ a menos que uses content collections.
Páginas de React
Sección titulada “Páginas de React”Tus páginas JSX (.js) de Next existentes necesitarán ser convertidas de archivos JSX a páginas .astro. No puedes usar un archivo de página JSX existente en Astro.
Estas páginas .astro deben estar ubicadas dentro de src/pages/ y tendrán rutas de página generadas automáticamente basadas en su ruta de archivo.
Páginas Markdown y MDX
Sección titulada “Páginas Markdown y MDX”Astro tiene soporte integrado para Markdown y una integración opcional para archivos MDX. Puedes reutilizar cualquier archivo Markdown y MDX existente, pero pueden requerir algunos ajustes en su frontmatter, como añadir la propiedad especial de frontmatter layout de Astro. Ya no necesitarás crear páginas manualmente para cada ruta generada por Markdown. Estos archivos pueden colocarse dentro de src/pages/ para aprovechar el enrutamiento automático basado en archivos.
Alternativamente, puedes usar content collections en Astro para almacenar y gestionar tu contenido. Recuperarás el contenido tú mismo y generarás esas páginas dinámicamente.
Migrar tests
Sección titulada “Migrar tests”Como Astro devuelve HTML crudo, es posible escribir tests end-to-end usando la salida del paso de build. Cualquier test end-to-end escrito previamente podría funcionar out-of-the-box si has podido igualar el markup de tu sitio de Next. Librerías de testing como Jest y React Testing Library pueden importarse y usarse en Astro para testear tus componentes de React.
Consulta la guía de testing de Astro para más.
Referencia: Convertir sintaxis de Next.js a Astro
Sección titulada “Referencia: Convertir sintaxis de Next.js a Astro”Links de Next a Astro
Sección titulada “Links de Next a Astro”Convierte cualquier componente de Next <Link to="">, <NavLink> etc. a etiquetas HTML <a href="">.
<Link to="/blog">Blog</Link><a href="/blog">Blog</a>Astro no usa ningún componente especial para links, aunque eres libre de construir tu propio componente <Link>. Luego puedes importar y usar este <Link> igual que cualquier otro componente.
---const { to } = Astro.props;---<a href={to}><slot /></a>Imports de Next a Astro
Sección titulada “Imports de Next a Astro”Actualiza cualquier importación de archivos para referenciar rutas de archivos relativas exactamente. Esto se puede hacer usando alias de importación, o escribiendo una ruta relativa completa.
Ten en cuenta que los archivos .astro y varios otros tipos de archivo deben importarse con su extensión completa.
---import Card from "../../components/Card.astro";---<Card />Children Props de Next a Astro
Sección titulada “Children Props de Next a Astro”Convierte cualquier instancia de {children} a un <slot /> de Astro. Astro no necesita recibir {children} como una prop de función y renderizará automáticamente el contenido hijo en un <slot />.
------export default function MyComponent(props) { return ( <div> {props.children} </div> );}
<div> <slot /></div>Los componentes de React que pasan múltiples conjuntos de children se pueden migrar a un componente de Astro usando named slots.
Ve más sobre uso específico de <slot /> en Astro.
Data Fetching de Next a Astro
Sección titulada “Data Fetching de Next a Astro”Convierte cualquier instancia de getStaticProps() a import.meta.glob() o getCollection()/getEntry() para acceder a datos de otros archivos en el código fuente de tu proyecto. Para obtener datos remotos, usa fetch().
Estas solicitudes de datos se hacen en el frontmatter del componente de Astro y usan top-level await.
---import { getCollection } from 'astro:content';
// Get all `src/content/blog/` entriesconst allBlogPosts = await getCollection('blog');
// Get all `src/pages/posts/` entriesconst allPosts = Object.values(import.meta.glob('../pages/posts/*.md', { eager: true }));
const response = await fetch('https://randomuser.me/api/');const data = await response.json();const randomUser = data.results[0];---Ve más sobre importaciones de archivos locales con import.meta.glob(), consultas con content collections o obtención de datos remotos.
Styling de Next a Astro
Sección titulada “Styling de Next a Astro”Puede que necesites reemplazar cualquier librería CSS-in-JS (p. ej. styled-components) con otras opciones de CSS disponibles en Astro.
Si es necesario, convierte cualquier objeto de estilo inline (style={{ fontWeight: "bold" }}) a atributos de estilo HTML inline (style="font-weight:bold;"). O, usa una etiqueta <style> de Astro para estilos CSS scoped.
<div style={{backgroundColor: `#f4f4f4`, padding: `1em`}}>{message}</div><div style="background-color: #f4f4f4; padding: 1em;">{message}</div>Tailwind es soportado después de instalar el plugin de Vite de Tailwind. ¡No se requieren cambios a tu código de Tailwind existente!
Ve más sobre estilos en Astro.
Next Image Plugin a Astro
Sección titulada “Next Image Plugin a Astro”Convierte cualquier componente <Image /> de Next a el propio componente de imagen de Astro en archivos .astro o .mdx, o a una etiqueta HTML estándar <img> / JSX <img /> según corresponda en tus componentes de React.
El componente <Image /> de Astro funciona solo en archivos .astro y .mdx. Consulta una lista completa de sus atributos de componente y ten en cuenta que varios diferirán de los atributos de Next.
---import { Image } from 'astro:assets';import rocket from '../assets/rocket.png';---<Image src={rocket} alt="A rocketship in space." /><img src={rocket.src} alt="A rocketship in space.">En componentes de React (.jsx), usa sintaxis de imagen JSX estándar (<img />). Astro no optimizará estas imágenes, pero puedes instalar y usar paquetes NPM para más flexibilidad.
Puedes aprender más sobre el uso de imágenes en Astro en la guía de Images.
Ejemplo guiado: Data fetching de Next a Astro
Sección titulada “Ejemplo guiado: Data fetching de Next a Astro”Aquí hay un ejemplo de data fetching de la Pokédex de Next.js convertido a Astro.
pages/index.js obtiene y muestra una lista de los primeros 151 Pokémon usando la REST PokéAPI.
Aquí te mostramos cómo recrear eso en src/pages/index.astro, reemplazando getStaticProps() con fetch().
-
Identifica el JSX del return().
pages/index.js import Link from 'next/link'import styles from '../styles/poke-list.module.css';export default function Home({ pokemons }) {return (<><ul className={`plain-list ${styles.pokeList}`}>{pokemons.map((pokemon) => (<li className={styles.pokemonListItem} key={pokemon.name}><Link className={styles.pokemonContainer} as={`/pokemon/${pokemon.name}`} href="/pokemon/[name]"><p className={styles.pokemonId}>No. {pokemon.id}</p><img className={styles.pokemonImage} src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemon.id}.png`} alt={`${pokemon.name} picture`}></img><h2 className={styles.pokemonName}>{pokemon.name}</h2></Link></li>))}</ul></>)}export const getStaticProps = async () => {const res = await fetch("https://pokeapi.co/api/v2/pokemon?limit=151")const resJson = await res.json();const pokemons = resJson.results.map(pokemon => {const name = pokemon.name;// https://pokeapi.co/api/v2/pokemon/1/const url = pokemon.url;const id = url.split("/")[url.split("/").length - 2];return {name,url,id}});return {props: {pokemons,},}} -
Crea
src/pages/index.astroUsa el valor de return de la función de Next. Convierte cualquier sintaxis de Next o React a Astro, incluyendo cambiar el caso de cualquier atributo global de HTML.
Ten en cuenta que:
-
.mapsimplemente funciona! -
classNamese convierte enclass. -
<Link>se convierte en<a>. -
El fragment
<> </>no es necesario en las plantillas de Astro. -
keyes un atributo de React, y no es un atributo delien Astro.
src/pages/index.astro ------<ul class="plain-list pokeList">{pokemons.map((pokemon) => (<li class="pokemonListItem"><a class="pokemonContainer" href={`/pokemon/${pokemon.name}`}><p class="pokemonId">No. {pokemon.id}</p><img class="pokemonImage" src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemon.id}.png`} alt={`${pokemon.name} picture`}/><h2 class="pokemonName">{pokemon.name}</h2></a></li>))}</ul> -
-
Añade cualquier import, prop y JavaScript necesario
Ten en cuenta que:
- la función
getStaticPropsya no es necesaria. Los datos de la API se obtienen directamente en el code fence. - Un componente
<Layout>se importa y envuelve la plantilla de página.
src/pages/index.astro ---import Layout from '../layouts/layout.astro';const res = await fetch("https://pokeapi.co/api/v2/pokemon?limit=151");const resJson = await res.json();const pokemons = resJson.results.map(pokemon => {const name = pokemon.name;// https://pokeapi.co/api/v2/pokemon/1/const url = pokemon.url;const id = url.split("/")[url.split("/").length - 2];return {name,url,id}});---<Layout><ul class="plain-list pokeList">{pokemons.map((pokemon) => (<li class="pokemonListItem" key={pokemon.name}><a class="pokemonContainer" href={`/pokemon/${pokemon.name}`}><p class="pokemonId">No. {pokemon.id}</p><img class="pokemonImage" src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemon.id}.png`} alt={`${pokemon.name} picture`}/><h2 class="pokemonName">{pokemon.name}</h2></a></li>))}</ul></Layout> - la función
Recursos de la comunidad
Sección titulada "Recursos de la comunidad"Si encontraste (¡o hiciste!) un video o blog post útil sobre convertir un sitio de Next.js a Astro, añádelo a esta lista!