Introduction
SQLite est une base de données relationnelle embarquée, légère et sans serveur, parfaite pour les applications Node.js locales ou prototypes rapides. Contrairement à PostgreSQL ou MySQL qui nécessitent un serveur dédié, SQLite stocke tout dans un seul fichier .db, ce qui simplifie le déploiement et réduit les coûts. En 2026, avec l'essor des apps edge et offline-first (comme les PWAs ou les outils CLI), SQLite reste incontournable pour sa fiabilité et sa portabilité.
Ce tutoriel beginner vous guide pour intégrer SQLite via better-sqlite3, une bibliothèque synchrone et performante. Nous construirons une API CRUD complète pour gérer une liste de tâches : création de table, insertion, lecture, mise à jour et suppression. Chaque étape est illustrée par du code TypeScript fonctionnel, prêt à copier-coller. À la fin, vous maîtriserez les bases pour des apps production-ready. Temps estimé : 15 minutes.
Prérequis
- Node.js 20+ installé
- Connaissances basiques en TypeScript et SQL
- Un éditeur comme VS Code
- Terminal (bash ou PowerShell)
Initialiser le projet et installer les dépendances
mkdir sqlite-todo-app
cd sqlite-todo-app
npm init -y
npm install better-sqlite3 typescript @types/node ts-node
npm install -D @types/better-sqlite3Cette commande crée un projet Node.js, initialise package.json et installe better-sqlite3 pour les interactions SQLite synchrones. TypeScript est ajouté pour la typage statique, évitant les erreurs runtime. Lancez npx tsc --init après pour configurer tsconfig.json.
Configurer TypeScript et créer la base de données
import Database from 'better-sqlite3';
const db = new Database('todos.db');
db.exec(`
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT FALSE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
console.log('Base de données initialisée avec table todos.');
export default db;Ce code ouvre (ou crée) le fichier todos.db et exécute une requête SQL pour créer la table todos si elle n'existe pas. Les colonnes incluent un ID auto-incrémenté, un titre, un statut booléen et une date de création. C'est idempotent grâce à IF NOT EXISTS, évitant les erreurs sur relance.
Implémenter la création (INSERT) de tâches
import db from './db';
const insertTodo = db.prepare('INSERT INTO todos (title) VALUES (?)');
const newTodo = insertTodo.run('Apprendre SQLite');
console.log('Tâche créée :', newTodo.lastInsertRowid);On prépare une requête INSERT paramétrée pour insérer une nouvelle tâche. run() exécute et retourne des métadonnées comme l'ID généré. Les paramètres ? préviennent les injections SQL, une bonne pratique sécurité dès le début.
Lire toutes les tâches (SELECT)
import db from './db';
const selectAll = db.prepare('SELECT * FROM todos ORDER BY created_at DESC');
const todos = selectAll.all();
console.log('Toutes les tâches :', todos);La méthode prepare() optimise les requêtes répétées. all() récupère toutes les lignes comme un tableau d'objets. ORDER BY trie par date récente pour une UX intuitive. Testez après création pour voir les données.
Mettre à jour une tâche (UPDATE)
import db from './db';
const updateTodo = db.prepare('UPDATE todos SET completed = ? WHERE id = ?');
const changes = updateTodo.run(true, 1);
console.log('Tâches modifiées :', changes.changes);Cette UPDATE marque une tâche comme complétée via son ID. run() retourne le nombre de lignes affectées (changes). Utilisez toujours WHERE pour cibler précisément et éviter des mises à jour massives accidentelles.
Supprimer une tâche (DELETE) et fermer la DB
import db from './db';
const deleteTodo = db.prepare('DELETE FROM todos WHERE id = ?');
const changes = deleteTodo.run(1);
console.log('Tâches supprimées :', changes.changes);
db.close();
console.log('Base de données fermée.');DELETE supprime par ID. Toujours fermer la DB avec close() en fin d'app pour libérer les ressources et éviter les verrouillages de fichier. Exécutez les scripts dans l'ordre pour tester le CRUD complet.
Script principal pour exécuter le CRUD complet
import db from './db';
import './createTodo';
import './readTodos';
import './updateTodo';
import './deleteTodo';
// Nettoyage final
db.close();
console.log('Démonstration CRUD terminée. Vérifiez todos.db !');Ce fichier orchestre tous les scripts pour un flux complet. Lancez avec npx ts-node index.ts. Il démontre un cycle CRUD réaliste. Le fichier todos.db persiste les changements entre exécutions.
Bonnes pratiques
- Préparez toujours les requêtes : Utilisez
prepare()pour la performance et la sécurité anti-injection. - Gérez les transactions : Pour les opérations multiples, wrappez dans
db.transaction()afin d'assurer l'atomicité. - Backup réguliers : Copiez
*.dbavant migrations ; utilisezdb.backup()pour des exports. - Indexez les colonnes : Ajoutez
CREATE INDEX idx_title ON todos(title);pour accélérer les recherches. - Fermez la DB : Appel systématique de
close()en fin de vie de l'app.
Erreurs courantes à éviter
- Oublier
IF NOT EXISTS: Provoque des crashes sur relance ; toujours idempotent. - Pas de
WHEREen UPDATE/DELETE : Risque de tout modifier/supprimer. - Ne pas fermer la DB : Fichier verrouillé, erreurs d'accès concurrent.
- Ignorer les types : SQLite est typé faiblement ; validez en JS/TS pour cohérence.
Pour aller plus loin
Maîtrisez les migrations avec prisma.io ou knexjs.org. Explorez Drizzle ORM pour TypeScript pur. Découvrez nos formations Learni sur les bases de données pour Node.js avancé et architectures scalables.