Pourquoi Next.js avec Prisma : guide pratique ?
Dans un monde où les développeurs sont souvent confrontés à des projets croissants et complexes, il est essentiel d'adopter des outils et des frameworks qui facilitent la gestion de la base de données tout en offrant une structure solide pour le développement. Next.js et Prisma sont deux technologies puissantes qui, ensemble, offrent une solution complète et performante pour les applications web modernes.
En tant que développeur senior avec plus de 10 ans d'expérience dans l'utilisation de frameworks React et gestion des bases de données, je comprends le besoin d'un guide pratique pour intégrer efficacement Next.js avec Prisma. Ce tutoriel vous aidera à comprendre les concepts fondamentaux, à mettre en pratique la technologie avec un mini-projet complet, et même à dépanner les erreurs courantes qui peuvent survenir lors de l'utilisation de ces outils.
Prerequis
Avant de commencer ce guide, assurez-vous d'avoir les connaissances suivantes :
- Maîtrise des concepts de base de React et Next.js.
- Connaissance du cycle de vie des composants React.
- Expérience avec la gestion de bases de données SQL et NoSQL.
- Familiarité avec les outils de ligne de commande (bash, terminal).
Vous devrez également installer les outils suivants :
- Node.js v14.0 ou supérieur
- npm 6.0 ou supérieur
- Prisma CLI v3.0 ou supérieur
Concepts fondamentaux
1. Next.js
Next.js est un framework React pour le développement d'applications web serveur-side render (SSR) et applications isomorphes. Il simplifie l'écriture de code côté serveur tout en offrant une performance optimale.
Exemple de code :
// pages/index.js
import { useState, useEffect } from 'react';
export default function Home() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then((res) => res.json())
.then((data) => setData(data));
}, []);
return (
<div>
<h1>Bienvenue sur Next.js avec Prisma</h1>
{data ? <p>Données : {JSON.stringify(data)}</p> : <p>Chargement...</p>}
</div>
);
}
2. Prisma
Prisma est une ORM (Object-Relational Mapping) moderne pour les applications Node.js et TypeScript. Il permet de travailler avec la base de données en utilisant un langage orienté objet tout en offrant des fonctionnalités avancées comme le suivi des changements, la gestion des relations et la migration des bases de données.
Exemple de code :
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
3. Migrations
Prisma utilise une gestion de migrations pour gérer les changements de schéma de la base de données. Les migrations permettent d'appliquer des modifications au schéma de manière sûre et réversible.
Exemple de commande :
npx prisma migrate dev --name init
4. Relations
Prisma facilite la gestion des relations entre les modèles de données en utilisant une syntaxe intuitive.
Exemple de code :
// prisma/schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
}
Mise en pratique : projet fil rouge
Pour mettre en pratique ce que nous avons appris, nous allons créer un mini-projet simple : une application de gestionnaire de tâches. Cette application permettra d'ajouter, modifier et supprimer des tâches.
Étape 1 : Initialisation du projet
npx create-next-app@latest task-manager
cd task-manager
Étape 2 : Installation de Prisma
npm install prisma --save-dev
npx prisma init
Étape 3 : Configuration de la base de données
Modifiez le fichier .env pour ajouter les informations de connexion à votre base de données.
Exemple de contenu :
DATABASE_URL="postgresql://user:password@localhost:5432/task_manager"
Étape 4 : Définition du schéma Prisma
Modifiez le fichier prisma/schema.prisma pour définir les modèles Task et User.
Exemple de code :
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Task {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
description String?
completed Boolean @default(false)
userId Int
user User @relation(fields: [userId], references: [id])
}
model User {
id Int @id @default(autoincrement())
email String @unique @db.VarChar(255)
name String?
createdAt DateTime@default(now())
updatedAt DateTime@updatedAt
}
Étape 5 : Création des migrations
npx prisma migrate dev --name init
Étape 6 : Définition des services Prisma
Créez un fichier prisma/service.ts pour définir les fonctions de base CRUD.
Exemple de code :
// prisma/service.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export async function createTask(data: any) {
return await prisma.task.create({ data });
}
export async function getTasks(userId: number) {
return await prisma.task.findMany({
where: { userId },
include: { user: true }
});
}
export async function updateTask(id: number, data: any) {
return await prisma.task.update({
where: { id },
data
});
}
export async function deleteTask(id: number) {
return await prisma.task.delete({ where: { id } });
}
Étape 7 : Définition des composants React
Créez les composants pour afficher et gérer les tâches.
Exemple de code :
// pages/index.js
import { useState, useEffect } from 'react';
import { createTask, getTasks, updateTask, deleteTask } from '../prisma/service';
export default function Home() {
const [tasks, setTasks] = useState([]);
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
useEffect(() => {
fetch('/api/tasks')
.then((res) => res.json())
.then((data) => setTasks(data));
}, []);
async function handleAddTask() {
if (title.trim()) {
await createTask({ title, description });
setTitle('');
setDescription('');
setTasks([...tasks, { id: Date.now(), title, description, completed: false }]);
}
}
async function handleUpdateTask(id, data) {
await updateTask(id, data);
setTasks(tasks.map((task) => (task.id === id ? { ...task, ...data } : task)));
}
async function handleDeleteTask(id) {
await deleteTask(id);
setTasks(tasks.filter((task) => task.id !== id));
}
return (
<div>
<h1>Gestionnaire de Tâches</h1>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Titre"
/>
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="Description"
/>
<button onClick={handleAddTask}>Ajouter Tâche</button>
{tasks.map((task) => (
<div key={task.id}>
<h2>{task.title}</h2>
<p>{task.description}</p>
<input
type="checkbox"
checked={task.completed}
onChange={(e) =>
handleUpdateTask(task.id, { completed: e.target.checked })
}
/>
<button onClick={() => handleDeleteTask(task.id)}>Supprimer</button>
</div>
))}
</div>
);
}
Erreurs frequentes et debugging
1. Erreur de connexion à la base de données
Code incorrect :
// pages/index.js
import { useState, useEffect } from 'react';
export default function Home() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then((res) => res.json())
.then((data) => setData(data));
}, []);
return (
<div>
<h1>Bienvenue sur Next.js avec Prisma</h1>
{data ? <p>Données : {JSON.stringify(data)}</p> : <p>Chargement...</p>}
</div>
);
}
Code correct :
// pages/index.js
import { useState, useEffect } from 'react';
export default function Home() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/tasks')
.then((res) => res.json())
.then((data) => setData(data));
}, []);
return (
<div>
<h1>Gestionnaire de Tâches</h1>
{data ? <p>Données : {JSON.stringify(data)}</p> : <p>Chargement...</p>}
</div>
);
}
2. Erreur de migration
Code incorrect :
npx prisma migrate dev --name init
Code correct :
npx prisma migrate dev --name add_user_table
3. Erreur de syntaxe Prisma
Code incorrect :
// prisma/schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
Code correct :
// prisma/schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique @db.VarChar(255)
name String?
}
Pour aller plus loin
1. Authentification avec NextAuth.js
Intégrez l'authentification sécurisée dans votre application en utilisant NextAuth.js.
2. Optimisation des performances
Améliorez les performances de votre application en utilisant la pagination et la mise en cache des données.
3. Déploiement sur Vercel
Déployez votre application Next.js avec Prisma sur Vercel pour bénéficier d'un hébergement rapide et évolutif.
Défi pratique
Créez une application de gestion de blog simple qui permet d'ajouter, modifier et supprimer des articles. Utilisez Prisma pour gérer la base de données et Next.js pour le rendu serveur-side.