Next.js 14 : Server Actions et les nouvelles fonctionnalités
Équipe Dev Ring
Équipe Dev Ring
Next.js 14 marque une étape importante avec la stabilisation des Server Actions et de nombreuses améliorations de performance grâce au nouveau compilateur Turbo.
Les Server Actions permettent d'exécuter du code serveur directement depuis les composants clients, simplifiant drastiquement la gestion des formulaires et des mutations de données.
// app/actions.ts
'use server'
import { revalidatePath } from 'next/cache'
import { db } from '@/lib/db'
export async function createPost(formData: FormData) {
const title = formData.get('title') as string
const content = formData.get('content') as string
// Validation côté serveur
if (!title || !content) {
throw new Error('Titre et contenu requis')
}
// Insertion en base de données
await db.post.create({
data: { title, content }
})
revalidatePath('/posts')
}
// app/create-post/page.tsx
import { createPost } from '../actions'
export default function CreatePost() {
return (
<form action={createPost}>
<input name="title" placeholder="Titre" required />
<textarea name="content" placeholder="Contenu" required />
<button type="submit">Créer</button>
</form>
)
}Le compilateur Turbo apporte des gains de performance considérables :
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
turbo: {
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
},
},
}
module.exports = nextConfigUne nouvelle approche hybride combinant le rendu statique et dynamique :
import { Suspense } from 'react'
import { Header } from '@/components/header'
import { Navigation } from '@/components/navigation'
import { Footer } from '@/components/footer'
import { ProductDetails, ProductSkeleton } from '@/components/product'
export default function ProductPage({ params }: { params: { id: string } }) {
return (
<div>
{/* Contenu statique - pré-rendu */}
<Header />
{/* Contenu dynamique - rendu à la demande */}
<Suspense fallback={<ProductSkeleton />}>
<ProductDetails id={params.id} />
</Suspense>
{/* Contenu statique - pré-rendu */}
</div>
)
}Meilleure gestion des métadonnées pour le SEO :
import type { Metadata } from 'next'
// Métadonnées statiques
export const metadata: Metadata = {
title: 'Mon Article',
description: "Description de l'article",
openGraph: {
images: ['./opengraph-image.jpg'],
},
}
// Métadonnées dynamiques
export async function generateMetadata(
{ params }: { params: { id: string } }
): Promise<Metadata> {
const post = await getPost(params.id)
return {
title: post.title,
description: post.excerpt,
openGraph: {
images: [post.coverImage],
},
}
}Permet d'afficher plusieurs pages simultanément :
// app/dashboard/layout.tsx
export default function Layout({
children,
analytics,
team,
}: {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
}) {
return (
<>
{children}
{analytics}
{team}
</>
)
}Intercepter des routes pour des modales ou overlays :
// app/photos/(..)photo/[id]/page.tsx
import Image from 'next/image'
import { Modal } from '@/components/modal'
export default function PhotoModal({ params }: { params: { id: string } }) {
return (
<Modal>
<Image src={`/photos/${params.id}.jpg`} alt="Photo" width={1200} height={800} />
</Modal>
)
}import Image from 'next/image'
// Optimisation automatique avec placeholders
export function HeroImage() {
return (
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={600}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
priority
sizes="(max-width: 768px) 100vw, 50vw"
/>
)
}# Installation
npm install next@latest react@latest react-dom@latest
# Mise à jour du package.json
# (exemple)
# {
# "scripts": {
# "dev": "next dev --turbo",
# "build": "next build",
# "start": "next start"
# }
# }Next.js 14 inclut des améliorations pour le monitoring :
// next.config.js
module.exports = {
experimental: {
instrumentationHook: true,
},
}
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./instrumentation.node')
}
if (process.env.NEXT_RUNTIME === 'edge') {
await import('./instrumentation.edge')
}
}import { useFormStatus } from 'react-dom'
import { redirect } from 'next/navigation'
function SubmitButton() {
const { pending } = useFormStatus()
return (
<button type="submit" disabled={pending}>
{pending ? 'Envoi...' : 'Envoyer'}
</button>
)
}
// Dans vos Server Actions
export async function createUser(formData: FormData) {
// ... logique de création
redirect('/users')
}Next.js 14 représente un bond en avant significatif pour l'écosystème React, offrant de nouvelles possibilités tout en maintenant une excellente developer experience.
Les Server Actions simplifient énormément le développement full-stack, tandis que Turbopack améliore considérablement les performances de développement. Ces améliorations, combinées aux nouvelles fonctionnalités de routing et de rendu, font de Next.js 14 un choix incontournable pour les projets React modernes.