Skip to content
Learni
Voir tous les tutoriels
Développement Backend

Comment configurer Drizzle ORM en 2026

Read in English

Introduction

Drizzle ORM est un ORM léger et TypeScript-first conçu pour les développeurs qui veulent une expérience type-safe sans le poids des outils comme Prisma. En 2026, il domine grâce à sa proximité avec SQL natif, ses performances optimales et son intégration parfaite avec Next.js ou Node.js pur. Contrairement aux ORMs traditionnels qui génèrent du code opaque, Drizzle vous laisse écrire des schémas en TypeScript qui se transforment en requêtes SQL précises.

Ce tutoriel beginner vous guide pas à pas pour créer un projet complet : installation, définition de schéma, connexion DB, migrations et opérations CRUD sur une table Users avec SQLite (idéal pour tester sans serveur externe). À la fin, vous aurez un script fonctionnel qui insère, lit, met à jour et supprime des données. Pourquoi c'est crucial ? Drizzle réduit les bugs runtime de 80% via l'inférence de types, accélère les queries et simplifie les migrations. Prêt à bookmark ce guide référence ? (142 mots)

Prérequis

  • Node.js 20+ installé
  • Connaissances de base en TypeScript (types, imports)
  • Éditeur comme VS Code avec extension TypeScript
  • Pas de base de données externe requise (SQLite embarqué)

Initialiser le projet et installer les dépendances

terminal
mkdir drizzle-tutorial && cd drizzle-tutorial
npm init -y
npm install drizzle-orm better-sqlite3
drizzle-kit install
npm install -D typescript @types/node tsx
mkdir src
drizzle-kit generate:sqlite

Cette commande initialise un projet Node.js, installe Drizzle ORM avec le driver SQLite (better-sqlite3 pour des perfs optimales), le kit de migrations, TypeScript et tsx pour exécuter les scripts TS. Le dernier generate:sqlite prépare les outils de migration. Exécutez-la en une fois pour un setup propre ; évitez npm install global pour l'isolation.

Configurer TypeScript et les scripts

Avant de plonger dans le cœur de Drizzle, configurez TypeScript et ajoutez des scripts NPM pour simplifier les commandes. Cela garantit une compilation sans erreurs et un workflow fluide.

package.json avec scripts utiles

package.json
{
  "name": "drizzle-tutorial",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "db:generate": "drizzle-kit generate",
    "db:push": "drizzle-kit push:sqlite",
    "db:migrate": "tsx src/migrate.ts"
  },
  "dependencies": {
    "drizzle-orm": "^0.32.0",
    "better-sqlite3": "^10.0.0"
  },
  "devDependencies": {
    "@types/node": "^22.0.0",
    "drizzle-kit": "^0.24.0",
    "tsx": "^4.19.0",
    "typescript": "^5.6.0"
  }
}

Ce package.json active ESM (type: module), ajoute des scripts pour dev, migrations (push pour SQLite dev) et utilise tsx pour hot-reload. Copiez-collez pour remplacer le vôtre. Piège : sans "type": "module", les imports TS échouent.

tsconfig.json pour TypeScript strict

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ES2022"],
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "noEmit": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*"]
}

Configuration TypeScript optimisée pour Drizzle : strict: true active la type-safety maximale, moduleResolution: bundler évite les conflits ESM. Pas d'émission (noEmit) car tsx compile à la volée. Analogie : comme un garde-barrière pour vos types.

Définir la configuration Drizzle

La config centrale pilote les migrations et l'introspection DB. Pour SQLite, c'est ultra-simple.

drizzle.config.ts

drizzle.config.ts
import type { Config } from 'drizzle-kit';

export default {
  schema: './src/schema.ts',
  out: './drizzle',
  dialect: 'sqlite',
  dbCredentials: {
    url: './sqlite.db',
  },
} satisfies Config;

Ce fichier pointe vers votre schéma TS, génère les migrations dans ./drizzle et utilise SQLite local. satisfies Config assure la validation types. Piège : mauvais chemin schema casse les db:generate. Exécutez npm run db:generate après création du schéma.

Créer le schéma de base de données

Analogie : Le schéma est comme un blueprint architectural – Drizzle l'utilise pour inférer types et générer SQL. Définissons une table users simple.

src/schema.ts

src/schema.ts
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';

import { relations } from 'drizzle-orm';

export const users = sqliteTable('users', {
  id: integer('id', { mode: 'number' }).primaryKey({ autoIncrement: true }),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
});

export const usersRelations = relations(users, ({ many }) => ({
  // Relations futures ici
}));

Table users avec ID auto-incrémenté (mode 'number' pour TS), nom et email unique. relations prépare les liens (ex: one-to-many). Types inférés automatiquement pour queries. Copiez, puis npm run db:generate pour voir le SQL généré.

Connecter à la base de données

La connexion est un wrapper fin autour du driver natif – pas de magie noire, juste Drizzle.

src/db.ts

src/db.ts
import Database from 'better-sqlite3';
import { drizzle } from 'drizzle-orm/better-sqlite3';
import * as schema from './schema';

const sqlite = new Database('./sqlite.db');

export const db = drizzle(sqlite, { schema });

Crée un DB handle SQLite et l'exporte via Drizzle pour type-safety. ./sqlite.db est créé auto. Import * as schema active l'inférence complète. Utilisez db partout pour queries.

Appliquer les migrations

Pour SQLite en dev, push applique directement. En prod, utilisez migrations versionnées.

Exécuter les migrations

terminal
npm run db:generate
npm run db:push

generate crée le SQL depuis schéma TS, push l'exécute atomiquement. Vérifiez ./drizzle/ pour migrations. Piège : sans push, vos queries échouent sur table manquante.

Implémenter les opérations CRUD

Voici le cœur : un script complet pour tester INSERT, SELECT, UPDATE, DELETE avec types parfaits.

src/index.ts - CRUD complet

src/index.ts
import { db } from './db';
import { users } from './schema';
import { eq, like, asc } from 'drizzle-orm';

(async () => {
  // INSERT
  const newUser = await db.insert(users).values({
    name: 'Alice',
    email: 'alice@example.com',
  }).returning();
  console.log('Inserted:', newUser);

  // SELECT all
  const allUsers = await db.select().from(users).orderBy(asc(users.id));
  console.log('All users:', allUsers);

  // SELECT by email
  const user = await db.select().from(users).where(eq(users.email, 'alice@example.com'));
  console.log('User by email:', user[0]);

  // UPDATE
  await db.update(users).set({ name: 'Alice Updated' }).where(eq(users.id, user[0]?.id!));
  console.log('Updated');

  // DELETE
  await db.delete(users).where(eq(users.id, user[0]?.id!));
  console.log('Deleted');

  process.exit(0);
})();

Script async complet : insère avec returning() (tous les champs retournés), sélectionne avec eq/like, trie asc, update/delete par ID. Lancez npm run dev ou npx tsx src/index.ts. Types inférés : user[0] est typé ! Erreur si champ manquant.

Bonnes pratiques

  • Toujours utiliser returning() pour éviter queries extra et garder la cohérence.
  • Migrations en CI/CD : drizzle-kit push en dev, migrate en prod.
  • Relations explicites : Définissez-les tôt pour joins type-safe.
  • Environnement vars : process.env.DATABASE_URL pour URL DB en prod.
  • Tests unitaires : Mockez db avec vitest pour queries isolées.

Erreurs courantes à éviter

  • Oublier db:push : Table inexistante → erreur SQL "no such table".
  • Mauvais dialect : SQLite ≠ PostgreSQL → migrations foireuses.
  • Pas de schema dans drizzle() : Perte d'inférence types (erreurs runtime).
  • ESM sans type: module : Imports import * cassés → SyntaxError.

Pour aller plus loin