Fermer

mars 22, 2024

Répertoire des pages d’adieu : voici comment migrer vers le routeur d’applications dans Next.js

Répertoire des pages d’adieu : voici comment migrer vers le routeur d’applications dans Next.js


Découvrez comment mettre à niveau votre projet Next.js dès aujourd’hui et profitez des avantages des composants App Router et React Server lorsque vous migrez depuis le répertoire Pages.

Next.js est un framework React complet qui offre de nombreuses fonctionnalités intéressantes, telles que la génération de sites statiques, le rendu côté serveur, le routage du système de fichiers et bien plus encore. Dans la version 13.4, Next.js a publié une version stable du Routeur d’applicationce qui change la façon dont les développeurs peuvent créer leurs applications.

L’App Router a introduit une nouvelle façon de créer des pages avec des itinéraires et des mises en page imbriquées. Il offre une récupération de données simplifiée, un streaming et des composants React Server en tant que citoyen de première classe. Il est clair qu’App Router est la direction dans laquelle Next.js se dirige, voyons donc comment migrer vers lui à partir du répertoire Pages.

Migration de Pages vers le répertoire d’applications

Next.js facilite la création de nouvelles pages dans une application. Il utilise le système de fichiers comme API et crée des routes pour chaque fichier du répertoire pages. Prenons comme exemple la structure de dossiers suivante :

Pages : structure des répertoires

src/
└── pages/
    ├── index.js
    ├── about.js
    └── contact/
        └── index.js

Pour ces fichiers, Next.js créerait ces routes :

  • src/pages/index.js -> /
  • src/pages/about.js -> /à propos
  • src/pages/contact/index.js -> /contact

C’est un peu différent lorsque vous utilisez l’App Router. Tout le code de l’App Router doit être placé à l’intérieur du app annuaire. Voici comment nous créerions les pages susmentionnées avec l’App Router.

Routeur d’applications : structure des répertoires

src/
└── app/
    ├── page.js
    ├── about/
    │   └── page.js
    └── contact/
        └── page.js

Chaque composant de page doit être appelé pageet son extension peut être soit js, jsx ou tsx. Comme pour le répertoire Pages, les noms de dossiers sont des segments utilisés pour créer des noms de routes, mais les fichiers de composants doivent toujours être appelés. page.

Itinéraires dynamiques

Il existe des situations dans lesquelles nous ne connaissons pas le nom exact d’un segment d’URL. Par exemple, nous pourrions avoir une page qui devrait afficher le profil de l’utilisateur en fonction de l’identifiant de l’utilisateur dans l’URL. C’est là que les itinéraires dynamiques entrent en jeu. Dans le répertoire Pages, cela peut être réalisé en plaçant le nom d’un dossier ou d’un fichier entre crochets : urn:uuid:7be4f52a-58bf-4112-986a-5668b51f93d0 ou [slug].

Pages : itinéraires dynamiques

src/
└── pages/
    ├── user/
    │   └── urn:uuid:7be4f52a-58bf-4112-986a-5668b51f93d0.js
    └── article/
        └── [slug]/
            └── index.js

Pour accéder à l’ID de l’utilisateur à partir de l’URL du composant d’annuaire Pages, nous devons utiliser le routeur Next.js, comme indiqué ci-dessous :

Pages : accès aux paramètres d’URL

import { useRouter } from "next/router";

const UserProfile = props => {
  const router = useRouter();
  return <div>User ID: {router.query.id}</div>;
};

export default UserProfile;

Et voici comment nous pouvons réaliser la même chose avec l’App Router.

Routeur d’applications : itinéraires dynamiques

src/
└── app/
    ├── article/
    │   └── [slug]/
    │       └── page.js
    └── user/
        └── urn:uuid:7be4f52a-58bf-4112-986a-5668b51f93d0/
            └── page.js

Puisque chaque composant de page doit être appelé page, nous devons ajouter des crochets dans les noms de dossiers. Le code ci-dessous montre comment accéder aux paramètres d’URL dynamiques :

App Router : accès aux paramètres d’URL

const User = props => {
  const { params, searchParams } = props;
  return <div>User ID: {params.id}</div>;
};

export default User;

Nous n’avons plus besoin d’utiliser le useRouter crochet, comme params et searchParams sont transmis via des accessoires.

Une chose très importante à noter est que chaque composant de l’App Router est, par défaut, un composant React Server (RSC). Cela signifie que les composants sont rendus uniquement sur le serveur. Il n’y a pas de processus d’hydratation côté client et tout code JavaScript lié au composant serveur est ignoré et n’est pas envoyé au client. Si tu ne sais pas quoi Les composants du serveur React le sont, consultez cette page.

Si vous souhaitez modifier un composant RSC en composant client, vous pouvez le faire en ajoutant le "use client" directive en haut du fichier.

"use client"

const User = props => {
  const { params, searchParams } = props;
  return <div>User ID: {params.id}</div>;
};

export default User;

Génération de site statique (SSG), rendu côté serveur (SSR) et régénération statique incrémentielle (ISR)

Next.js peut générer des pages statiques au moment de la construction ou des pages dynamiques au moment de l’exécution sur le serveur. Dans le répertoire des pages, il existait trois approches principales pour récupérer des données avant de générer des pages :getStaticProps avec ou sans revalidation et getServerSideProps. getStaticProps est appelé lorsque l’application est construite avec le next build commande, tandis que cette dernière est appelée au moment de l’exécution lorsqu’un utilisateur fait une demande pour voir une page.

Il est cependant possible de restituer le revalidate propriété de getStaticProps pour tourner la page de la génération de site statique (SSG) à la régénération statique incrémentielle (ISR). La différence est qu’au lieu de générer la page au moment de la construction, la page est générée au moment de l’exécution, tout comme avec getServerSideProps. La page est régénérée en fonction du revalidate propriété. Voyons comment nous pouvons les migrer vers l’App Router.

L’exemple ci-dessous montre comment utiliser getStaticProps pour récupérer et afficher une liste de messages.

Pages : getStaticProps (SSG)

export const getStaticProps = async () => {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts");

  return {
    props: {
      posts: await response.json(),
    },
    
    revalidate: 60
  };
};

const Articles = props => {
  const { posts } = props;
  return (
    <div>
      <h1>Articles</h1>
      <ul>
        {posts.map(post => {
          return <li key={post.id}>{post.title}</li>;
        })}
      </ul>
    </div>
  );
};

export default Articles;

Pages—getServerSideProps

export const getServerSideProps = async context => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/users/${context.params.id}`
  );

  return {
    props: {
      user: await response.json(),
    },
  };
};

const UserProfile = props => {
  const { user } = props;
  return (
    <div>
      <div>User ID: {user.id}</div>
      <div> Name: {user.name}</div>
    </div>
  );
};

export default UserProfile;

Dans l’App Router, nous n’utilisons pas getStaticProps et getServerSideProps. Au lieu de cela, toutes les récupérations de données doivent être effectuées dans les composants serveur.

Les composants React normaux doivent être synchrones, mais les composants React Server peuvent être asynchrones. Par conséquent, nous utilisons async/await pour effectuer des requêtes API à l’intérieur des composants, puis utiliser les données récupérées pour renvoyer le balisage JSX.

Ci-dessous, nous avons un exemple de la façon d’implémenter un équivalent de getStaticProps.

Routeur d’applications : équivalent à getStaticProps

const Articles = async props => {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
    cache: "force-cache",
  });

  const posts = await response.json();
  return (
    <div>
      <h1>Articles</h1>
      <ul>
        {posts.map(post => {
          return <li key={post.id}>{post.title}</li>;
        })}
      </ul>
    </div>
  );
};

export default Articles;

À l’intérieur du Articles composant, nous faisons une requête API en utilisant fetch. L’élément clé ici est le cache: "force-cache" valeur. Next.js étend le natif Fetch API pour améliorer les fonctionnalités des composants du serveur. Dans ce scénario, les données renvoyées par l’API seront mises en cache.

Il convient de noter que toutes les requêtes effectuées à l’aide de fetch qui ne précise pas le cache la valeur sera mise en cache par défaut. Donc, cache: "force-cache"peut en fait être omis.

Dans une situation où les données doivent être revalidées, nous pouvons spécifier le next.revalidate option et réglez-la sur un certain nombre de secondes. Le code ci-dessous montre comment revalider les données mises en cache toutes les 30 secondes.

Routeur d’applications : getStaticProps avec revalidation (ISR)

const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
  next: {
    revalidate: 30
  }
}); 

Enfin et surtout, nous avons getServerSideProps équivalent.

Routeur d’applications : équivalent à getServerSideProps

const User = async props => {
  const { params, searchParams } = props;
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/users/${params.id}`,
    {
      cache: "no-store",
    }
  );
  const user = await response.json();
  return (
    <div>
      <div>User ID: {user.id}</div>
      <div> Name: {user.name}</div>
    </div>
  );
};

export default User;

La seule différence avec le getStaticProps un exemple équivalent est qu’au lieu de passer cache: "force-cache" au fetchil doit être réglé sur no-store.

getStaticPaths

Un composant Page peut exporter une fonction appelée getStaticPaths pour définir des chemins dynamiques pour les pages qui doivent être générées au moment de la construction.

export async function getStaticPaths() {
  return {
    paths: [
      {
        params: {
          slug: 'hello-app-router'
        },
        params: {
          slug: 'migrating-from-next-pages'
        }
      }
    ]
  }
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://domain.com/articles/${params.slug}`)
 
  return { 
    props: { 
      article: await res.json()
    } 
  }
}

export default function Article(props) {
  return <DisplayArticle article={props.article} />
}

Lors de l’utilisation de l’App Router, nous devons appeler la fonction generateStaticParams au lieu de getStaticPaths.

Routeur d’applications : équivalent à getStaticPaths

export async function generateStaticParams() {
  return {
    paths: [
      {
        params: {
          slug: 'hello-app-router'
        },
        params: {
          slug: 'migrating-from-next-pages'
        }
      }
    ]
  }
}

export default function Article(props) {
  const res = await fetch(`https://domain.com/articles/${props.params.slug}`)
  const article = await res.json()
  return <DisplayArticle article={article} />
}

Itinéraires API

La création de points de terminaison d’API est un jeu d’enfant dans Next.js, car il utilise le système de fichiers pour générer des points de terminaison d’API. Pour créer un point de terminaison API dans le répertoire Pages, nous devons créer un fichier qui exporte un gestionnaire dans le src/pages/api annuaire.

Pages : structure de routage de l’API

src/
└── pages/
    └── api/
        └── articles.js

Pages : exemple de route API

export default async function handler(req, res) {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts");
  res.status(200).json(await response.json());
}

La création de points de terminaison d’API dans App Router est assez similaire, mais avec quelques différences. Tous les fichiers de route API doivent être nommés route.js. Par conséquent, pour obtenir la même route API que celle que nous venons de faire avec les pages, nous aurions besoin de créer le route.js fichier dans le app/api/articles dossier.

App Router : structure du gestionnaire de route

src/
└── app/
    └── api/
        └── articles/
            └── route.js

Le route.js file doit également exporter une fonction de gestionnaire, mais il existe une différence importante. Au lieu d’utiliser le default export pour fournir une fonction de gestionnaire, les routes de l’API App Router doivent exporter une fonction nommée comme les méthodes HTTP.

App Router : exemple de gestionnaire de route

import { NextResponse } from "next/server";

export async function GET(request) {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts");
  return NextResponse.json({
    posts: await response.json(),
  });
}

Next.js prend en charge les méthodes HTTP suivantes : GET, POST, PATCH, DELETE, HEAD et OPTIONSet en fait, un gestionnaire de route API peut exporter plusieurs gestionnaires.

export async function GET(request) {} 
export async function POST(request) {}
export async function PATCH(request) {} 
export async function DELETE(request) {}

Conclusion

La migration du répertoire Pages vers App Router dans Next.js offre un contrôle de route amélioré, des routes dynamiques, des routes API, une gestion flexible du middleware et des stratégies de rendu améliorées avec SSG et SSR. En adoptant les composants React Server, nous pouvons optimiser les performances et l’interactivité. Mettez à niveau votre projet Next.js dès aujourd’hui et profitez des avantages des composants App Router et React Server.




Source link