Nouveau : Datasets open source gratuits disponibles !Decouvrir →
Intermediaire 25 min Next.js

Migrer de Create React App vers Next.js

Pourquoi Migrer de Create React App vers Next.js ?

La migration d'un projet React existant de Create React App (CRA) vers Next.js peut sembler intimidante, mais elle est en réalité une opportunité de tirer parti des nombreuses fonctionnalités avancées et des meilleures pratiques qui rendent Next.js le choix idéal pour les applications modernes. En effet, CRA est bien adapté aux petites applications ou aux petits projets individuels, tandis que Next.js offre une grande flexibilité, un meilleur SEO, et la possibilité de créer des applications universelles (SSR, SSG, ISR).

Un cas d'usage concret serait le développement d'une application de blogging. Avec CRA, vous pourriez avoir du mal à gérer efficacement les routes dynamiques, tandis que Next.js permettrait d'avoir une structure de route claire et des pages dynamiques facilement configurables.

Prerequis

  • Connaissances en React
  • Familiarité avec JavaScript ES6+
  • Installation de Node.js (v14.0.0 ou plus)
  • Installation de npm (Node Package Manager)

Concepts fondamentaux

1. Pages

Next.js utilise les fichiers du répertoire pages pour définir la structure des routes de votre application. Chaque fichier dans ce répertoire correspond à une route.

// pages/index.js
export default function Home() {
  return <div>Bienvenue sur le Blog</div>;
}

2. Styles

Next.js supporte les fichiers CSS et SCSS directement dans les composants React.

// pages/about.js
import styles from '../styles/About.module.css';

export default function About() {
  return (
    <div className={styles.container}>
      <h1>A propos</h1>
      <p>Next.js est génial !</p>
    </div>
  );
}

3. Routing

Les routes sont automatiquement générées à partir des fichiers dans le répertoire pages.

// pages/blog/[slug].js
export default function Post({ post }) {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
}

export async function getStaticPaths() {
  // Fetch posts data from an API or a database
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();

  const paths = posts.map((post) => ({
    params: { slug: post.slug },
  }));

  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  // Fetch the data for this specific blog post
  const res = await fetch(`https://api.example.com/posts/${params.slug}`);
  const post = await res.json();

  return { props: { post } };
}

4. API Routes

Next.js vous permet de créer des routes d'API qui peuvent être appelées depuis le client ou directement par le serveur.

// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ name: 'John Doe' });
}

Mise en pratique : projet fil rouge

Nous allons créer un simple blog avec des routes dynamiques et une API pour récupérer les posts.

Étape 1 : Initialiser le Projet

npx create-next-app@latest nextjs-blog
cd nextjs-blog

Étape 2 : Créer les Composants

Créez un fichier components/Post.js pour afficher un post.

// components/Post.js
import styles from '../styles/Post.module.css';

export default function Post({ post }) {
  return (
    <div className={styles.post}>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
}

Étape 3 : Créer la Route Dynamique

Créez un fichier pages/blog/[slug].js pour afficher les détails d'un post.

// pages/blog/[slug].js
import Head from 'next/head';
import { useEffect, useState } from 'react';
import Post from '../components/Post';

export default function BlogPost({ initialPost }) {
  const [post, setPost] = useState(initialPost);

  useEffect(() => {
    // Fetch post data if it's not already available
    if (!initialPost) {
      fetch(`https://api.example.com/posts/${slug}`)
        .then((res) => res.json())
        .then((data) => setPost(data));
    }
  }, [initialPost]);

  return (
    <div>
      <Head>
        <title>{post.title}</title>
      </Head>
      {post && <Post post={post} />}
    </div>
  );
}

export async function getStaticPaths() {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();

  const paths = posts.map((post) => ({
    params: { slug: post.slug },
  }));

  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  // Fetch the data for this specific blog post
  const res = await fetch(`https://api.example.com/posts/${params.slug}`);
  const post = await res.json();

  return { props: { initialPost: post } };
}

Étape 4 : Créer la Page d'Accueil

Créez un fichier pages/index.js pour afficher la liste des posts.

// pages/index.js
import Head from 'next/head';
import Link from 'next/link';

export default function Home({ posts }) {
  return (
    <div>
      <Head>
        <title>Blog</title>
      </Head>
      <h1>Blog</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.slug}>
            <Link href={`/blog/${post.slug}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

export async function getStaticProps() {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();

  return { props: { posts } };
}

Étape 5 : Créer l'API pour les Posts

Créez un fichier pages/api/posts.js pour récupérer la liste des posts.

// pages/api/posts.js
export default function handler(req, res) {
  const posts = [
    { slug: 'post1', title: 'Premier Post', content: 'Contenu du premier post' },
    { slug: 'post2', title: 'Deuxième Post', content: 'Contenu du deuxième post' },
  ];

  res.status(200).json(posts);
}

Erreurs frequentes et debugging

1. Error: Expected server HTML to contain a matching <div> in <div>

Cela se produit souvent lorsqu'il y a une différence entre le rendu côté serveur et le client.

// ❌ Mauvais
import React from 'react';

function MyComponent() {
  return (
    <div>
      <h1>Hello World</h1>
    </div>
  );
}

export default MyComponent;

Corrigez-le en ajoutant une clé unique aux éléments.

// ✅ Correct
import React from 'react';

function MyComponent() {
  return (
    <div key="unique-key">
      <h1>Hello World</h1>
    </div>
  );
}

export default MyComponent;

2. Error: A component must be returned from a render method, or null instead of undefined.

Cela se produit lorsque vous n'avez pas retourné une valeur à partir d'une fonction React.

// ❌ Mauvais
import React from 'react';

function MyComponent() {
  if (condition) {
    return <div>Hello World</div>;
  }
}

Corrigez-le en ajoutant un else pour retourner null.

// ✅ Correct
import React from 'react';

function MyComponent({ condition }) {
  if (condition) {
    return <div>Hello World</div>;
  } else {
    return null;
  }
}

export default MyComponent;

3. Error: Failed to load resource: the server responded with a status of 404 (Not Found)

Cela se produit lorsque le serveur ne trouve pas la route demandée.

// pages/blog/[slug].js
import { useEffect, useState } from 'react';

export default function BlogPost({ initialPost }) {
  const [post, setPost] = useState(initialPost);

  useEffect(() => {
    if (!initialPost) {
      fetch(`https://api.example.com/posts/${slug}`)
        .then((res) => res.json())
        .then((data) => setPost(data));
    }
  }, [initialPost]);

  return (
    <div>
      {post && <h1>{post.title}</h1>}
    </div>
  );
}

export async function getStaticPaths() {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();

  const paths = posts.map((post) => ({
    params: { slug: post.slug },
  }));

  return { paths, fallback: true };
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.slug}`);
  const post = await res.json();

  return { props: { initialPost: post } };
}

Pour aller plus loin

1. Navigation avec next/link

Utilisez le composant Link pour naviguer entre les pages.

// pages/index.js
import Link from 'next/link';

export default function Home() {
  return (
    <div>
      <h1>Blog</h1>
      <ul>
        <li>
          <Link href="/blog/post1">
            <a>Premier Post</a>
          </Link>
        </li>
        <li>
          <Link href="/blog/post2">
            <a>Deuxième Post</a>
          </Link>
        </li>
      </ul>
    </div>
  );
}

2. Optimisation des Images avec next/image

Utilisez le composant Image pour optimiser les images.

// components/Post.js
import Image from 'next/image';

export default function Post({ post }) {
  return (
    <div className={styles.post}>
      <h1>{post.title}</h1>
      {post.image && (
        <Image src={post.image} alt={post.title} width={500} height={300} />
      )}
      <p>{post.content}</p>
    </div>
  );
}

3. Hydratation Asynchrone avec getServerSideProps

Utilisez getServerSideProps pour récupérer les données côté serveur.

// pages/blog/[slug].js
export async function getServerSideProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.slug}`);
  const post = await res.json();

  return { props: { post } };
}

Défi Pratique

Créez un mini-projet de gestionnaire de tâches en utilisant Next.js. Le projet devrait permettre d'afficher une liste de tâches, d'ajouter de nouvelles tâches, et de marquer les tâches comme terminées.

Besoin d'aide sur Next.js ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Comment puis-je conserver mes fichiers .css et .scss lors de la migration ?
Pour conserver vos fichiers .css et .scss, vous pouvez les déplacer dans le répertoire `styles` du projet Next.js et les importer comme vous le feriez dans un composant React.
Quelles sont les principales différences entre Create React App et Next.js ?
Create React App est parfait pour des applications frontales simples avec une seule page, tandis que Next.js est conçu pour des applications à plusieurs pages nécessitant du rendu côté serveur (SSR).
Comment puis-je migrer mes composants React existants vers Next.js ?
Vous pouvez commencer par créer un nouveau projet Next.js et intégrer vos composants React existants. Assurez-vous de configurer les routes et les API endpoints en fonction de vos besoins.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.