Retour • 09/02/2025
Guide complet de Prisma avec NextJS
Écris par Melvyn Malherbe le 09/02/2025
Je vais t'expliquer comment utiliser Prisma dans une application JavaScript en prenant notamment l'exemple de NextJS.
Ce guide va tout t'expliquer :
- Comment installer Prisma
- Comment fonctionne le système de migration de Prisma
- Comment utiliser Prisma dans ton application
- Usage avancé de Prisma
- Prisma avec TypeScript
Comment installer Prisma
Prisma vient avec deux librairies :
prisma
C'est la librairie principale de Prisma qui va être installée dans les dépendances de dev. Elle permet principalement d'exécuter des commandes dans le terminal pour faire des actions.
@prisma/client
C'est la librairie qui va être dans les dépendances et c'est elle qui va permettre de faire des requêtes à la base de données.
Pour installer Prisma, il y a une commande qu'on peut exécuter :
npx prisma initCette commande va installer les dépendances nécessaires et rajouter un dossier prisma dans ton projet avec un fichier schema.prisma.
Ce fichier schema.prisma va nous permettre de définir les tables de notre base de données.
On va partir sur le principe que tu utilises PostgreSQL comme base de données, tu vas devoir modifier le fichier schema.prisma pour ajouter ta DATABASE_URL dans le fichier .env.
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}Et dans ton fichier .env, tu vas ajouter :
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgresEnsuite tu peux ajouter tes tables et relations. Voici l'exemple de la documentation :
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String @db.VarChar(255)
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model Profile {
id Int @id @default(autoincrement())
bio String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
profile Profile?
}Ici tu peux voir qu'on a des relations, en installant l'extension VSCode Prisma tu verras qu'il t'aide super bien à créer des schémas cohérents.
Une fois qu'on a ajouté ça, on doit créer une migration.
Comment fonctionne le système de migration de Prisma
Le système de migration est un système populaire dans les bases de données qui permet de venir modifier la structure de ta base de données de manière évolutive.
C'est-à-dire que chaque fois qu'on va modifier le schéma, on va créer une migration, cette migration va venir modifier la base de données et potentiellement les données.
Ensuite quand on vient lancer la migration, celle-ci va appliquer chaque migration dans l'ordre, ce qui permet de faire des migrations sans risquer de perdre des données.
Pour créer une migration, on peut utiliser la commande suivante :
npx prisma migrate devCette commande va créer une migration et l'appliquer à la base de données. Tu verras qu'il va te demander un nom pour la migration, tu peux simplement inscrire "init database" ou "initial migration".
Modification de la base de données
Imagine qu'on souhaite remplacer name par firstname et lastname dans notre schéma. Dans ce cas-là, on va modifier
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
firstname String?
lastname String?
posts Post[]
profile Profile?
}Dans ce cas-là c'est compliqué car on va perdre des données, car si on fait une migration qui supprime le champ name et rajoute firstname et lastname, on va perdre toutes les données de name.
Pour éviter ça, on va créer une nouvelle migration qui va venir ajouter les champs firstname et lastname et les remplir avec les données de name.
npx prisma migrate --create-only --name add-firstname-lastnameCette commande va créer un fichier de migration dans ton projet, tu peux le voir dans le dossier prisma/migrations.
Ensuite on va pouvoir faire du SQL :
- Ajouter les champs
firstnameetlastname - Remplir le champ
firstnamepar le champname - Supprimer le champ
name
Voici le code SQL :
ALTER TABLE "User" ADD COLUMN "firstname" text;
ALTER TABLE "User" ADD COLUMN "lastname" text;
UPDATE "User" SET "firstname" = "name";
ALTER TABLE "User" DROP COLUMN "name";Et de cette manière, quand on va déployer notre site sur notre database de production, la migration va se faire et on va éviter de perdre des données.
Cette migration va ensuite s'effectuer chaque fois qu'on va lancer les migrations sur une "nouvelle base de données".
Les migrations viennent générer le @prisma/client
Le @prisma/client est généré en fonction de ton schéma. C'est-à-dire que tous les types sont générés chaque fois que tu fais une migration. Tu peux aussi générer les types avec la commande suivante :
npx prisma generateCette commande va venir générer le @prisma/client et les types dans le dossier node_modules.
C'est comme ça qu'ensuite tu vas pouvoir faire des requêtes à la base de données de manière "type-safe".
Comment utiliser Prisma dans ton application
Pour ajouter Prisma, on va utiliser un Singleton expliqué dans la documentation.
Dans un fichier lib/prisma.ts on va instancier notre Prisma :
// lib/prisma.ts
import { PrismaClient } from '~/generated/client';
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;Ce code permet d'éviter d'instancier plusieurs fois le PrismaClient dans ton application. Notamment quand tu publies l'application sur Vercel en "Serverless".
Une fois fait, tu peux utiliser prisma à n'importe quel endroit backend de ton application, comme un API Routes qui viendrait retourner tous les posts dans app/api/posts/route.ts :
import { NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
export async function GET(request: Request) {
const posts = await prisma.post.findMany();
return NextResponse.json(posts);
}Ce code vient récupérer tous les posts disponibles et vient les retourner en format JSON. Tu peux le voir ici, mais avec Prisma tout est type-safe c'est-à-dire que quand tu écris prisma. tu as une auto-complétion automatique sur VSCode qui te propose post.
Usage avancé de Prisma
Tu peux utiliser Prisma pour faire à peu près tout ce qui est possible de faire avec SQL sauf si tu vas dans des cas trop compliqués. Mais voici des exemples typiques.
Récupérer tous les posts qui commencent par "Pourquoi"
const posts = await prisma.post.findMany({
where: {
title: {
startsWith: 'Pourquoi',
},
},
});wherepermet de filtrer les données- il existe ensuite plein de filtres built-in
Récupérer l'user avec l'id 1 et tous ses posts
const user = await prisma.user.findUnique({
where: {
id: 1,
},
include: {
posts: true,
},
});
const posts = user.posts;includevient inclure des relations à la valeur de retour
Récupérer l'user le nom et le titre de tous les posts de l'utilisateur avec l'id 1
const posts = await prisma.post.findMany({
where: {
authorId: 1,
},
select: {
title: true,
author: {
select: { name: true },
},
},
});selectpermet de sélectionner et récupérer uniquement les champs dont tu as besoin. Tu peux aussi sélectionner des données dans les relations.
Récupérer le nombre de posts de l'utilisateur avec l'id 1
const posts = await prisma.post.count({
where: {
authorId: 1,
},
});countpermet de récupérer le nombre de données
Récupérer les 10 derniers posts
const posts = await prisma.post.findMany({
take: 10,
orderBy: {
createdAt: 'desc',
},
});takepermet de récupérer un nombre de donnéesorderBypermet de trier les données
Point sur les usages avancés
Il existe évidemment plein d'autres usages et de choses à faire. Je t'invite à utiliser ChatGPT si tu as des questions, il répond vraiment bien. Tu peux aussi lire la documentation.
Prisma avec TypeScript
Un truc que j'aime vraiment faire avec Prisma, c'est de générer des types TypeScript en fonction des query que je fais. Souvent dans mes applications je crée des méthodes pour séparer mes query de mes API Routes par exemple. Par exemple, je vais récupérer le user et ses posts dans une méthode :
export const getUserWithPosts = async (userId: number) => {
const user = await prisma.user.findUnique({
where: { id: userId },
select: {
id: true,
name: true,
posts: {
select: {
id: true,
title: true,
},
},
},
});
return user;
};Et ensuite souvent j'ai envie d'avoir un type qui correspond à cet objet. Pour ça, Prisma a prévu le coup et tu peux faire ceci.
import { Prisma } from '~/generated/client';
type UserWithPosts = Prisma.PromiseReturnType<typeof getUserWithPosts>;
// UserWithPosts = {
// id: number;
// name: string;
// posts: { id: number; title: string }[];
// }Et là, tu as un type qui correspond à l'objet que tu retournes dans ta fonction.
Tu peux donc créer un Server Component qui va prendre en props ce fameux user avec le bon type :
export const UserWithPostsCard = ({ user }: { user: UserWithPosts }) => {
return (
<div>
<h1>{user.name}</h1>
{user.posts.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</div>
);
};Et là, tu as une auto-complétion sur VSCode qui te propose les champs de l'objet.
L'avantage de dingue ici c'est que si tu viens modifier les données que tu récupères dans la méthode getUserWithPosts tu vas avoir TypeScript qui va automatiquement modifier le type et t'afficher ou non des erreurs en fonction. J'utilise ça tout le temps et c'est vraiment très puissant.
Conclusion
Dans ce guide je t'ai présenté les points les plus importants de Prisma ! J'ai une formation "NextReact" qui contient un module entier sur Prisma et tu peux tester ma formation gratuitement ici :
Deviens développeur Next.js fullstack !
+2000 élèves formés au développement moderne. Récupère ton accès gratuit à la formation.
Inscris ton e-mail pour recevoir ton accès privé :