2 min read

Next.js : Framework React Full-Stack

Créez des applications web modernes avec rendu côté serveur et génération statique

Utilisez Node.js 18.18 ou supérieur. Exécutez les commandes à la racine de votre projet.

Prérequis

node -v  # >= 18.18
npm -v

Si Node.js n'est pas installé, consultez la documentation nvm.

Démarrage rapide

# Créer un nouveau projet
npx create-next-app@latest mon-app

cd mon-app
npm run dev

Ouvrir http://localhost:3000

Structure du projet

mon-app/
├── app/
│   ├── layout.tsx      # Layout racine
│   ├── page.tsx        # Page d'accueil
│   └── about/
│       └── page.tsx    # Route /about
├── public/             # Fichiers statiques
├── next.config.js      # Configuration
└── package.json

Créer des pages

// app/page.tsx
export default function Home() {
  return <h1>Accueil</h1>
}

// app/blog/page.tsx
export default function Blog() {
  return <h1>Blog</h1>
}

// app/blog/[slug]/page.tsx
export default function Post({ params }: { params: { slug: string } }) {
  return <h1>Article : {params.slug}</h1>
}

Récupération de données

// app/posts/page.tsx
async function getPosts() {
  const res = await fetch('https://api.example.com/posts')
  return res.json()
}

export default async function Posts() {
  const posts = await getPosts()
  return (
    <ul>
      {posts.map(post => <li key={post.id}>{post.title}</li>)}
    </ul>
  )
}

Composants Client vs Serveur

// app/server-component.tsx (par défaut)
export default function ServerComponent() {
  return <div>Rendu côté serveur</div>
}

// app/client-component.tsx
'use client'
import { useState } from 'react'

export default function ClientComponent() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}

API Routes

// app/api/hello/route.ts
export async function GET() {
  return Response.json({ message: 'Hello' })
}

export async function POST(request: Request) {
  const body = await request.json()
  return Response.json({ received: body })
}

Layouts

// app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html lang="fr">
      <body>
        <header>Mon Site</header>
        {children}
        <footer>© 2025</footer>
      </body>
    </html>
  )
}

// app/dashboard/layout.tsx
export default function DashboardLayout({ children }) {
  return (
    <div>
      <nav>Menu Dashboard</nav>
      {children}
    </div>
  )
}
import Link from 'next/link'
import { useRouter } from 'next/navigation'

export default function Navigation() {
  const router = useRouter()
  
  return (
    <nav>
      <Link href="/">Accueil</Link>
      <Link href="/about">À propos</Link>
      <button onClick={() => router.push('/dashboard')}>
        Dashboard
      </button>
    </nav>
  )
}

Images optimisées

import Image from 'next/image'

export default function Profile() {
  return (
    <Image
      src="/photo.jpg"
      alt="Photo de profil"
      width={500}
      height={500}
      priority
    />
  )
}

Métadonnées SEO

// app/page.tsx
export const metadata = {
  title: 'Accueil',
  description: 'Bienvenue sur mon site'
}

// ou dynamique
export async function generateMetadata({ params }) {
  const post = await getPost(params.id)
  return {
    title: post.title,
    description: post.excerpt
  }
}

Variables d'environnement

# .env.local
DATABASE_URL=postgresql://...
NEXT_PUBLIC_API_URL=https://api.example.com
// Côté serveur uniquement
const dbUrl = process.env.DATABASE_URL

// Côté client (préfixe NEXT_PUBLIC_)
const apiUrl = process.env.NEXT_PUBLIC_API_URL

Scripts package.json

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
}

Build et déploiement

# Build pour production
npm run build

# Démarrer en mode production
npm start

# Analyser le bundle
npm install @next/bundle-analyzer
// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})

module.exports = withBundleAnalyzer({
  reactStrictMode: true,
})
ANALYZE=true npm run build

Configuration courante

// next.config.js
module.exports = {
  reactStrictMode: true,
  images: {
    domains: ['example.com'],
  },
  async redirects() {
    return [
      {
        source: '/old-page',
        destination: '/new-page',
        permanent: true,
      },
    ]
  },
}

Middleware

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')
  
  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url))
  }
  
  return NextResponse.next()
}

export const config = {
  matcher: '/dashboard/:path*',
}

Déploiement sur Vercel

npm install -g vercel
vercel login
vercel

En savoir plus