
Si vous développez des API en Node.js, vous respirez probablement du JSON et du REST à longueur de journée. C'est le standard, c'est flexible, et ça marche partout.
Mais avez-vous déjà eu l'impression que vos microservices "bavardaient" trop lentement ? Ou qu'une simple faute de frappe dans un nom de champ JSON faisait planter votre application en production ?
C'est là qu'intervient gRPC.
Dans cet article, nous allons voir comment cette technologie créée par Google peut transformer vos architectures Node.js, et nous allons construire ensemble votre premier client/serveur gRPC.
gRPC (gRemote Procedure Call) est un framework open-source qui permet à un service de communiquer avec un autre de manière extrêmement rapide et structurée.
Contrairement à REST qui envoie du texte (JSON) via HTTP/1.1, gRPC utilise :
HTTP/2 : Pour la performance (multiplexage, streaming).
Protocol Buffers (Protobuf) : Un format binaire ultra-léger pour les données.
Vitesse : Les messages binaires sont 7 à 10 fois plus rapides à sérialiser/désérialiser que le JSON.
Typage fort : Fini les erreurs undefined. Vous définissez un contrat strict. Si vous ne respectez pas le contrat, le code ne tourne pas.
Génération de code : Vous écrivez le contrat, et gRPC génère le code client et serveur pour vous (en JS, mais aussi en Go, Python, Java, etc.).
Assez de blabla. Mettons les mains dans le code. Nous allons créer une architecture simple :
Un Serveur qui possède des articles de news.
Un Client qui demande une news spécifique.
Créez un dossier pour votre projet et installez les dépendances gRPC pour Node.js :
mkdir grpc-tuto && cd grpc-tuto
npm init -y
npm install @grpc/grpc-js @grpc/proto-loaderNote : On utilise @grpc/grpc-js qui est l'implémentation pure JavaScript moderne, remplaçant l'ancienne librairie grpc native.
C'est la pièce maîtresse. Nous allons définir à quoi ressemblent nos données et nos fonctions dans un fichier nommé news.proto.
Créez le fichier news.proto à la racine :
syntax = "proto3";
package news;
// 1. Définition du Service
service NewsService {
rpc GetNews (NewsRequest) returns (NewsResponse) {}
}
// 2. Définition des Messages (les données)
message NewsRequest {
string id = 1; // On envoie un ID
}
message NewsResponse {
string id = 1;
string title = 2;
string body = 3;
string image_url = 4;
}Contrairement au JSON, chaque champ a un numéro unique (= 1, = 2). C'est ce qui permet de compresser les données en binaire : on n'envoie pas le mot "title" sur le réseau, juste le numéro 2.
Créez un fichier server.js. C'est ici que nous allons implémenter la logique.
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
// 1. Chargement du fichier .proto
const packageDefinition = protoLoader.loadSync('news.proto', {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const newsProto = grpc.loadPackageDefinition(packageDefinition).news;
// Données fictives (mock)
const newsData = [
{ id: "1", title: "Node.js 20 est sorti", body: "Voici les nouveautés...", image_url: "img1.jpg" },
{ id: "2", title: "gRPC vs REST", body: "Le combat des chefs...", image_url: "img2.jpg" }
];
// 2. Implémentation de la méthode GetNews
function getNews(call, callback) {
const newsId = call.request.id;
const newsItem = newsData.find(n => n.id === newsId);
if (newsItem) {
// Succès : null en erreur, et l'objet en réponse
callback(null, newsItem);
} else {
// Erreur : on renvoie une erreur gRPC standard
callback({
code: grpc.status.NOT_FOUND,
details: "News introuvable"
});
}
}
// 3. Démarrage du serveur
function main() {
const server = new grpc.Server();
// On lie notre implémentation au service défini dans le proto
server.addService(newsProto.NewsService.service, { GetNews: getNews });
const address = '127.0.0.1:50051';
server.bindAsync(address, grpc.ServerCredentials.createInsecure(), () => {
console.log(`🚀 Serveur gRPC démarré sur ${address}`);
server.start(); // Facultatif selon les versions, mais explicite
});
}
main();Maintenant, créons un script pour consommer notre API. Créez client.js.
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
// On charge le même fichier proto ! C'est le contrat partagé.
const packageDefinition = protoLoader.loadSync('news.proto', {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const newsProto = grpc.loadPackageDefinition(packageDefinition).news;
function main() {
// Création du client
const client = new newsProto.NewsService(
'127.0.0.1:50051',
grpc.credentials.createInsecure()
);
// Appel de la méthode
console.log("📡 Appel du service...");
client.GetNews({ id: "1" }, (error, response) => {
if (!error) {
console.log("✅ Réponse reçue du serveur :");
console.log(response);
} else {
console.error("❌ Erreur :", error.details);
}
});
}
main();Ouvrez un terminal et lancez le serveur :
node server.js2. Ouvrez un deuxième terminal et lancez le client :
node client.jsVous devriez voir :
📡 Appel du service...
✅ Réponse reçue du serveur :
{
id: '1',
title: 'Node.js 20 est sorti',
body: 'Voici les nouveautés...',
image_url: 'img1.jpg'
}Essayez de changer l'ID dans client.js par "99", et vous verrez l'erreur gRPC "News introuvable" s'afficher proprement.
Faut-il jeter toutes vos API REST Express ? Surtout pas.
Utilisez gRPC si :
Vous faites du Microservices : Vos services backend Node.js communiquent entre eux.
Vous avez besoin de Performance temps réel.
Vous travaillez dans une équipe Polyglotte : Un service Node.js doit parler à un service Python ou Go. Le fichier .proto met tout le monde d'accord.
Gardez REST si :
Vous faites une API publique pour des tiers.
Votre API est consommée directement par un navigateur (React/Vue) sans proxy intermédiaire (bien que gRPC-Web existe, c'est une complexité ajoutée).
gRPC n'est pas juste une "hype", c'est un outil puissant pour structurer vos communications backend. En tant que développeur JS, l'apprentissage est rapide et le gain en robustesse est immédiat.
Alors, prêt à écrire votre premier fichier .proto ?