Aller au contenu

Migration depuis Next.js

Voici quelques concepts clés et stratégies de migration pour vous aider à démarrer. Utilisez le reste de nos documents et notre communauté sur Discord pour continuer !

Principales similitudes entre Next.js et Astro

Titre de la section Principales similitudes entre Next.js et Astro

Next.js et Astro partagent certaines similitudes qui vous aideront à migrer votre projet :

Principales différences entre Next.js et Astro

Titre de la section Principales différences entre Next.js et Astro

Lorsque vous reconstruisez votre site Next.js dans Astro, vous remarquerez quelques différences importantes :

  • Next.js est une application React monopage et utilise index.js comme racine de votre projet. Astro est un site multipage et index.astro est votre page d’accueil.

  • Les composants .astro ne sont pas écrits sous forme de fonctions exportées renvoyant des modèles de page. Au lieu de cela, vous diviserez votre code en une « barrière de code » pour votre JavaScript et en un corps dédié au HTML que vous générez.

  • Axé sur le contenu : Astro a été conçu pour présenter votre contenu et pour vous permettre d’opter pour l’interactivité uniquement si nécessaire. Une application Next.js existante peut être conçue pour une interactivité élevée côté client et peut nécessiter des techniques Astro avancées pour inclure des éléments plus difficiles à répliquer à l’aide de composants .astro, tels que des tableaux de bord.

Chaque migration de projet sera différente, mais vous effectuerez certaines actions courantes lors de la conversion de Next.js vers Astro.

Utilisez la commande create astro de votre gestionnaire de paquets pour lancer l’assistant CLI d’Astro ou choisissez un thème de communauté dans la vitrine de thèmes Astro.

Vous pouvez utiliser un argument --template avec la commande create astro pour démarrer un nouveau projet Astro avec l’un de nos démarreurs officiels (par exemple docs, blog, portfolio). Vous pouvez également démarrer un nouveau projet à partir de n’importe quel dépôt Astro existant sur GitHub.

Fenêtre de terminal
# exécuter l'assistant CLI d'Astro
npm create astro@latest
# créer un nouveau projet en utilisant un exemple officiel
npm create astro@latest -- --template <example-name>

Ensuite, copiez les fichiers existants de votre projet Next vers votre nouveau projet Astro dans un dossier séparé en dehors de src.

Installer des intégrations (facultatif)

Titre de la section Installer des intégrations (facultatif)

Vous trouverez peut-être utile d’installer certaines des intégrations facultatives d’Astro à utiliser lors de la conversion de votre projet Next en Astro :

  • @astrojs/react: pour réutiliser certains de vos composants React orientés UI dans votre nouveau site Astro ou pour continuer à coder des composants React.

  • @astrojs/mdx: pour importer des fichiers MDX existants de votre projet Next ou pour utiliser MDX dans votre nouveau site Astro.

En suivant la structure du projet d’Astro:

  1. Gardez le dossier public/ de Next intact.

    Astro utilise le répertoire public/ pour les ressources statiques, tout comme Next. Aucune modification n’est nécessaire pour ce dossier, ni pour son contenu.

  2. Copiez ou déplacez les autres fichiers et dossiers de Next (par exemple, pages, styles, etc.) dans le dossier src/ d’Astro pendant que vous reconstruisez votre site en suivant la structure du projet Astro.

    Comme Next, le dossier src/pages/ d’Astro est un dossier spécial utilisé pour le routage basé sur des fichiers. Tous les autres dossiers sont facultatifs et vous pouvez organiser le contenu de votre dossier src/ comme vous le souhaitez. D’autres dossiers courants dans les projets Astro incluent src/layouts/, src/components, src/styles, src/scripts.

Astro possède un fichier de configuration à la racine de votre projet appelé astro.config.mjs. Ceci est utilisé uniquement pour configurer votre projet Astro et toutes les intégrations installées, y compris les adaptateurs SSR.

Astuces : Convertir les fichiers JSX en fichiers .astro

Titre de la section Astuces : Convertir les fichiers JSX en fichiers .astro

Voici quelques conseils pour convertir un composant Next .js en un composant .astro :

  1. Utilisez le JSX renvoyé par la fonction du composant Next.js existant comme base pour votre modèle HTML.

  2. Remplacez toute syntaxe Next ou JSX par une syntaxe Astro ou par des normes web HTML. Ceci comprend <Link>, <Script>, {children} et className par exemple.

  3. Déplacez tout le JavaScript nécessaire, y compris les instructions d’importation, dans une « barrière de code » (---). Remarque : le JavaScript utilisé pour afficher le contenu de manière conditionnelle est souvent écrit directement dans le modèle HTML dans Astro.

  4. Utilisez Astro.props pour accéder à toutes les propriétés supplémentaires précédemment transmises à votre fonction Next.

  5. Décidez si les composants importés doivent également être convertis en syntaxe Astro. Avec l’intégration officielle installée, vous pouvez utiliser les composants React existants dans votre fichier Astro. Mais vous souhaiterez peut-être les convertir en composants .astro, surtout s’ils n’ont pas besoin d’être interactifs !

  6. Remplacez getStaticProps() avec des déclarations d’importation ou avec Astro.glob() pour interroger vos fichiers locaux. Utilisez fetch() pour récupérer des données externes.

Voir un exemple d’un fichier.js converti étape par étape depuis Next.

Comparez le composant Next suivant et un composant Astro correspondant :

StarCount.jsx
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;

Vous trouverez peut-être utile de commencer par convertir vos mises en page et modèles Next.js en composants Astro de mise en page.

Next propose deux méthodes différentes pour créer des fichiers de mise en page, chacune gérant les mises en page différemment d’Astro :

Chaque page Astro nécessite explicitement la présence des balises <html>, <head> et <body>, il est donc courant de réutiliser un fichier de mise en page sur plusieurs pages. Astro utilise un <slot /> pour le contenu des pages sans aucune déclaration d’importation requise. Notez le modèle HTML standard et l’accès direct à <head> :

src/layouts/Layout.astro
---
---
<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>
<!-- Enveloppez l'élément slot avec votre modèle de mise en page existant -->
<slot />
</body>
</html>

Migration depuis le répertoire pages de Next.js

Titre de la section Migration depuis le répertoire pages de Next.js

Votre projet Next peut avoir un fichier pages/_document.jsx qui importe des composants React pour personnaliser le <head> de votre application :

pages/_document.jsx
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>
);
}
}
  1. Créez un nouveau fichier de mise en page Astro en utilisant uniquement le JSX renvoyé.

  2. Remplacez tous les composants React par <html>, <head>, <slot> et d’autres balises HTML standard.

    src/layouts/Document.astro
    <html lang="en">
    <head>
    <link rel="icon" href="/favicon.ico" />
    </head>
    <body>
    <slot/>
    </body>
    </html>

Migration depuis le répertoire /app de Next.js

Titre de la section Migration depuis le répertoire /app de Next.js

Les fichiers de mise en page du répertoire app/ de Next.js sont créés avec deux fichiers : un fichier layout.jsx pour personnaliser les contenus de <html> et de <body>, et un fichier head.jsx pour personnaliser le contenu de l’élément <head>.

app/layout.jsx
export default function Layout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
app/head.jsx
export default function Head() {
return (
<>
<title>Ma Page</title>
</>
);
}
  1. Créez un nouveau fichier de mise en page Astro en utilisant uniquement le JSX renvoyé.

  2. Remplacez ces deux fichiers par un seul fichier de mise en page Astro qui contient un shell de page (les balises <html>, <head> et <body>) et un <slot/> à la place de la propriété {children} de React :

    src/layouts/Layout.astro
    <html lang="en">
    <head>
    <title>Ma Page</title>
    </head>
    <body>
    <slot/>
    </body>
    </html>

Dans Next.js, vos articles se trouvent soit dans /pages, soit dans /app/routeName/page.jsx.

Avec Astro, tous les contenus de vos pages doivent vivre à l’intérieur du dossier src/, soit dans src/pages, soit dans src/content.

Vos pages Next JSX (.js) existantes devront être converties des fichiers JSX en pages .astro. Vous ne pouvez pas réutiliser un fichier JSX de page dans Astro.

Ces pages .astro doivent être situées dans src/pages/ et les routes des pages seront générées automatiquement en fonction de leur chemin de fichier.

Astro dispose d’une prise en charge intégrée pour Markdown et d’une intégration facultative pour les fichiers MDX. Vous pouvez réutiliser tous les fichiers Markdown et MDX existants, mais ils peuvent nécessiter quelques ajustements dans leur frontmatter, comme l’ajout de la propriété spéciale layout d’Astro. Vous n’aurez plus besoin de créer manuellement des pages pour chaque itinéraire généré par Markdown. Ces fichiers peuvent être placés dans src/pages/ pour profiter du routage automatique basé sur les fichiers.

Alternativement, vous pouvez utiliser les collections de contenu dans Astro pour stocker et gérer votre contenu. Lorsqu’ils font partie d’une collection, les fichiers Markdown et MDX résideront dans des dossiers dans src/content/. Vous récupérerez vous-même le contenu et générerez ces pages de manière dynamique.

Comme Astro génère du HTML brut, il est possible d’écrire des tests de bout en bout en utilisant la sortie de l’étape de construction. Tous les tests de bout en bout écrits précédemment peuvent fonctionner immédiatement si vous avez réussi à faire correspondre le balisage de votre site Next. Les bibliothèques de tests telles que Jest et React Testing Library peuvent être importées et utilisées dans Astro pour tester vos composants React.

Voir le guide de test d’Astro pour en savoir plus.

Référence : Convertir la syntaxe Next.js en syntaxe Astro

Titre de la section Référence : Convertir la syntaxe Next.js en syntaxe Astro

Convertissez tous les composants <Link to="">, <NavLink> etc. de Next en balises HTML <a href="">.

<Link to="/blog">Blog</Link>
<a href="/blog">Blog</a>

Astro n’utilise aucun composant spécial pour les liens, bien que vous puissiez créer votre propre composant <Link>. Vous pouvez ensuite importer et utiliser ce <Link> comme vous le feriez pour n’importe quel autre composant.

src/components/Link.astro
---
const { to } = Astro.props;
---
<a href={to}><slot /></a>

Mettez à jour toutes les importations de fichiers pour référencer exactement les chemins de fichiers relatifs. Cela peut être fait en utilisant des alias d’importation ou en écrivant un chemin relatif dans son intégralité.

Notez que .astro et plusieurs autres types de fichiers doivent être importés avec leur extension de fichier complète.

src/pages/authors/Fred.astro
---
import Card from "../../components/Card.astro";
---
<Card />

La propriété Children : de Next vers Astro

Titre de la section La propriété Children : de Next vers Astro

Convertissez toutes les instances de {children} en <slot /> Astro. Ce dernier n’a pas besoin de recevoir {children} comme propriété de fonction et restituera automatiquement le contenu enfant dans un <slot />.

src/components/MyComponent.astro
---
---
export default function MyComponent(props) {
return (
<div>
{props.children}
</div>
);
}
<div>
<slot />
</div>

Les composants React qui transmettent plusieurs ensembles d’enfants peuvent être migrés vers un composant Astro à l’aide des emplacements nommés.

En savoir plus sur l’utilisation spécifique de <slot /> dans Astro.

La récupération des données : de Next vers Astro

Titre de la section La récupération des données : de Next vers Astro

Convertissez toutes les instances de getStaticProps() en Astro.glob() ou getCollection()/getEntryBySlug() afin d’accéder aux données d’autres fichiers dans la source de votre projet. Pour récupérer des données distantes, utilisez fetch().

Ces demandes de données sont effectuées dans le frontmatter du composant Astro et utilisent une instruction await de niveau supérieur (« top-level await »).

src/pages/index.astro
---
import { getCollection } from 'astro:content';
// Get all `src/content/blog/` entries
const allBlogPosts = await getCollection('blog');
// Get all `src/pages/posts/` entries
const allPosts = await Astro.glob('../pages/posts/*.md');
const response = await fetch('https://randomuser.me/api/');
const data = await response.json();
const randomUser = data.results[0];
---

En savoir plus sur les importations de fichiers locaux avec Astro.glob(), l’interrogation à l’aide de l’API Collections ou la récupération de données distantes.

Vous devrez peut-être remplacer les bibliothèques CSS-in-JS (par exemple, styled-components) avec d’autres options CSS disponibles dans Astro.

Si nécessaire, convertissez tous les objets de style en ligne (style={{ fontWeight: "bold" }}) en attributs de style HTML en ligne (style="font-weight:bold;"). Ou utilisez la balise <style> d’Astro pour limiter la portée des styles CSS.

src/components/Card.astro
<div style={{backgroundColor: `#f4f4f4`, padding: `1em`}}>{message}</div>
<div style="background-color: #f4f4f4; padding: 1em;">{message}</div>

Tailwind est pris en charge après l’installation de l’intégration Tailwind. Aucune modification de votre code Tailwind existant n’est requise !

En savoir plus sur les styles dans Astro.

Le composant Next Image vers celui d’Astro

Titre de la section Le composant Next Image vers celui d’Astro

Convertissez tous les composants Next <Image /> en composant d’image propre à Astro dans les fichiers .astro ou .mdx, ou en code HTML/JSX standard avec la balise <img /> selon les besoins dans vos composants React.

Le composant <Image /> d’Astro fonctionne uniquement dans les fichiers .astro et .mdx. Consultez la liste complète de ses attributs de composants et notez que plusieurs différeront des attributs de Next.

src/pages/index.astro
---
import { Image } from 'astro:assets';
import rocket from '../assets/rocket.png';
---
<Image src={rocket} alt="Une fusée dans l'espace." />
<img src={rocket.src} alt="Une fusée dans l'espace.">

Dans les composants React (.jsx), utilisez la syntaxe d’image JSX standard (<img />). Astro n’optimisera pas ces images, mais vous pouvez installer et utiliser les packages NPM pour plus de flexibilité.

Vous pouvez en apprendre davantage sur l’utilisation d’images dans Astro dans le guide Images.

Exemple guidé : Récupération des données, de Next vers Astro

Titre de la section Exemple guidé : Récupération des données, de Next vers Astro

Voici un exemple de récupération de données Pokédex dans Next.js converties en Astro.

pages/index.js récupère et affiche une liste des 151 premiers Pokémon en utilisant la PokéAPI REST.

Voici comment recréer cela dans src/pages/index.astro, en remplaçant getStaticProps() par fetch().

  1. Identifiez la déclaration return() dans le JSX.

    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,
    },
    }
    }
  2. Créez src/pages/index.astro

    Utilisez la valeur de retour de la fonction Next. Convertissez n’importe quelle syntaxe Next ou React en Astro, y compris en modifiant la casse de tout attribut global HTML.

    Remarquez que :

    • .map fonctionne tout simplement !

    • className devient class.

    • <Link> devient <a>.

    • Le fragment <> </> n’est pas requis dans les modèles Astro.

    • key est un attribut React et n’est pas un attribut de li dans 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>
  3. Ajoutez les importations, les propriétés et le JavaScript nécessaires

    Remarquez que :

    • la fonction getStaticProps n’est plus nécessaire. Les données de l’API sont récupérées directement dans la barrière de code.
    • Un composant <Layout> est importé et enveloppe le modèle de page.
    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>

Plus de guides sur les migrations