À la découverte de…AdonisJS

L’écosystème de Node.js regorge de frameworks et de bibliothèques. Il y a environ trois ans, je vous ai présenté Fastify, une alternative sérieuse à Express.js. Aujourd’hui, je souhaite attirer votre attention sur AdonisJS, un framework lancé fin 2015. Bien qu’il ne soit pas nouveau, AdonisJS reste souvent méconnu, au profit d’autres frameworks, malgré ses nombreux atouts. Cet article a donc pour but de vous faire découvrir AdonisJS et tenter de susciter votre envie d’en apprendre davantage à son sujet, dans l’espoir de lui accorder la reconnaissance qu’il mérite dans l’univers de Node.js.

Remarque : Cet article n’est pas un tutoriel sur AdonisJS mais une présentation de celui-ci. Je partagerai des ressources utiles pour approfondir vos connaissances à la fin de l’article.

Petit tour d’horizon des frameworks Node.js

Dans l’écosystème de Node.js, on distingue deux grandes familles de frameworks, chacune répondant à des besoins et des approches de développement différents.

Les frameworks “low-scope”

Les frameworks « low-scope » offrent une toile vierge pour les développeurs. Ils se caractérisent par leur structure de base minimaliste, principalement un système de routage et des middlewares. Cette approche minimaliste offre une grande liberté dans la construction d’applications, permettant aux développeurs de choisir et d’intégrer des bibliothèques selon leurs besoins spécifiques. Cependant, cette liberté a un coût : le besoin de sélectionner et d’intégrer manuellement des bibliothèques pour des fonctionnalités avancées telles que l’accès aux données ou l’authentification des utilisateurs. Cela peut entraîner une augmentation du temps de développement et un besoin accru de prise de décision technique.

Parmi les frameworks “low-scope” les plus populaires, nous retrouvons :

Les frameworks “high-scope”

À l’opposé, les frameworks « high-scope » comme Nest.js proposent une solution plus complète dès le départ. Ils sont souvent livrés avec une gamme de fonctionnalités intégrées, telles que l’accès aux données (généralement via un ORM), l’authentification ou encore la validation des données réduisant ainsi la configuration initiale et les décisions techniques à prendre. Ces frameworks sont conçus pour optimiser le développement en adoptant des pratiques et des structures établies, permettant ainsi aux développeurs de se concentrer sur le cœur de l’application. Le revers de la médaille est moins de flexibilité et une courbe d’apprentissage potentiellement plus abrupte en raison de l’architecture et des conventions spécifiques du framework.

Qu’en est-il d’AdonisJS ?

AdonisJS se distingue en offrant une fusion unique entre ces deux mondes. Il fournit un noyau solide et des fonctionnalités de base comme un framework « low-scope », tout en permettant une extension facile avec des modules officiels qui enrichissent le framework, le rapprochant ainsi des frameworks « high-scope ». Ce mélange offre aux développeurs la liberté de choisir les modules nécessaires pour leur projet, sans les contraintes d’une structure trop rigide.

AdonisJS : un Framework complet et modulaire

AdonisJS est un framework Node.js open source, écrit en TypeScript. Lancé en octobre 2015, il a été créé et maintenu principalement par Harminder Virk, rejoint ensuite par trois autres développeurs formant l’équipe principale :

Avec plus d’une centaine de contributeurs, AdonisJS bénéficie également d’une riche communauté de développeurs.

Petit flashback

AdonisJS a parcouru un long chemin depuis sa première version en octobre 2015. Il a évolué à travers plusieurs versions majeures, chacune apportant des améliorations et de nouvelles fonctionnalités. En décembre 2015, la version 2.0 a été lancée, suivie par la 3.0 en juin 2016, et la 4.0 en juin 2017. Avec la sortie de la version 5.0 en mars 2020, AdonisJS a renforcé son architecture et a introduit une prise en charge complète de TypeScript.

La version 6 est quant à elle prévue pour le 24 janvier 2024. Cette nouvelle version arrive avec son lot de nouveauté, parmi lesquelles :

  • une adoption complète des modules ECMAScript (ESM);
  • L’obligation de Node.js version 20;
  • L’utilisation de Vite comme bundler par défaut;
  • Un nouveau module de validation des données (VineJS)

Dans la suite de l’article, nous allons nous concentrer sur cette version 6.

La Philosophie modulaire d’AdonisJS

L’architecture modulaire d’AdonisJS lui permet de fournir les fonctionnalités de base, communes aux frameworks “low-scope”, tout en offrant la possibilité d’intégrer une gamme de modules officiels pour des fonctionnalités supplémentaires. Cette flexibilité signifie que les développeurs peuvent adapter le framework à leurs besoins spécifiques, faisant d’AdonisJS un outil polyvalent adapté à divers types de projets.

Le cœur d’AdonisJS

Le cœur d’AdonisJS propose les fonctionnalités fondamentales suivantes :

  • Un système de routage et de contrôleurs;
  • Un système de middleware;
  • Un système de gestion de configurations et de variables d’environnement;
  • Un système d’émetteurs d’événements;
  • Un système de chiffrement et de hachage;
  • Un système de logging (basé sur Pino);
  • Un système d’injection de dépendances.
Les modules composant le cœur d’AdonisJS

AdonisJS offre une liberté similaire aux frameworks « low-scope » dans le sens où il permet de construire des applications en intégrant des modules externes. Cette flexibilité est importante à souligner, car il existe un malentendu commun selon lequel l’utilisation des modules officiels d’AdonisJS, comme Lucid, est obligatoire. En réalité, les développeurs ont la liberté de choisir parmi d’autres solutions telles que Prisma ou TypeORM.

Cependant, même si AdonisJS permet de développer des applications à la façon des frameworks “low-scope”, cette méthode peut ne pas être la plus efficace. L’écosystème Node.js a tendance à être un peu chaotique, avec une propension à réinventer la roue plutôt que de s’appuyer sur un framework “high-scope” bien établi. Cela contraste fortement avec l’écosystème PHP, où l’adoption de frameworks “high-scope” comme Laravel ou Symfony est monnaie courante et ne pose pas de problème.

Les modules officiels

La force d’AdonisJS réside dans la diversité et la richesse de ses modules officiels. Voici un aperçu de certains d’entre eux :

  • lucid : ORM pour les interactions avec les bases de données ;
  • auth : Gestion de l’authentification des utilisateurs ;
  • ally : Authentification sociale pour des plateformes telles que Github, Twitter, et Google ;
  • bouncer : Système de gestion des permissions et des rôles ;
  • drive : Gestion du stockage de fichiers, avec support de divers services (S3, GCS) ;
  • ace : Création d’interfaces de ligne de commande ;
  • vineJS : Bibliothèque pour la validation des données ;
  • japa : Framework de tests ;
  • shield : Protection contre les vulnérabilités web (XSS, CSRF, etc.) ;
  • transmit : Module SSE (Server-Sent Events) pour la diffusion en temps réel ;
  • i18n : Intégration de l’internationalisation et de la localisation.
Les modules officiels d’AdonisJS
Les modules officiels d’AdonisJS

Ces modules permettent aux développeurs d’adapter AdonisJS à leurs besoins, que ce soit pour des applications web simples ou des backends d’API complexes.

Les modules communautaires

L’écosystème AdonisJS se distingue par ses nombreux modules créés par la communauté. Ces modules couvrent différents domaines, tels que la sécurité, le monitoring, l’authentification, l’autorisation, le déploiement, les outils de développement, etc.

Pour explorer ces modules, je vous invite à visiter le site packages.adonisjs.com.

Le site packages.adonisjs.com fournit une multitude de modules
Le site packages.adonisjs.com fournit une multitude de modules

Enfin un vrai système intégré

AdonisJS se distingue parmi les frameworks Node.js grâce à son système intégré qui facilite l’extension et la personnalisation de ses modules. L’un des exemples de cette extensibilité est le module Lucid, qui peut étendre les fonctionnalités d’autres composants du framework. Par exemple Lors de l’installation de Lucid, de nouvelles règles sont ajoutées au système de validation de données, d’AdonisJS.

AdonisJS intègre également une interface de ligne de commande (CLI) via son module Ace. L’ajout de nouveaux modules à AdonisJS enrichit automatiquement la CLI avec de nouvelles commandes, consolidant les fonctionnalités dans une seule interface.

Cette méthode contraste avec celle de certains autres frameworks, comme Nest.js, où il est courant d’avoir des CLI distinctes pour chaque module installé, comme TypeORM ou Prisma. L’approche unifiée d’AdonisJS favorise une expérience de développement plus structurée, où les outils et commandes sont centralisés, simplifiant la gestion et l’utilisation du framework.

Ace fournit des commandes pour chaque module d’AdonisJS
Ace fournit des commandes pour chaque module d’AdonisJS

Un plugin VScode est également fournit avec AdonisJS proposant ainsi une expérience de développement agréable et peu commune dans l’écosystème Node.js.

Les commandes Ace sont disponibles directement depuis VScode via l'extension
Les commandes Ace sont disponibles directement depuis VScode via l’extension

Quelques exemples de code

L’exploration complète d’AdonisJS dépasse le cadre d’un seul article, étant donné la profondeur et l’étendue de ce framework. Cet article se veut une invitation à découvrir AdonisJS plutôt qu’un guide détaillé. Néanmoins, pour vous donner un avant-goût de sa puissance et de sa facilité d’utilisation, je vais vous proposer ici quelques exemples de code.

Le routing

Pour montrer comment fonctionne le routing, prenons l’exemple d’un contrôleur pour gérer des tâches. La création d’un nouveau contrôleur pour une ressource est simplifiée grâce à la commande suivante :

Les contrôleurs sont stockés dans le répertoire ./app/controllers. Chaque contrôleur est représenté sous forme d’une classe TypeScript standard :

AdonisJS utilise par convention ces différents noms de méthode, mais rien ne vous empêche d’utiliser les noms que vous souhaitez pour mieux s’adapter à vos besoins spécifiques.

Ensuite, il est important de lier ce contrôleur à une route. AdonisJS permet d’importer le contrôleur en utilisant l’alias #controllers. Les alias sont définis en utilisant la fonctionnalité d’imports de sous-chemins de Node.js.

La méthode router.get spécifie qu’il s’agit d’une route GET. Le premier argument tasks est le chemin de l’URL et le deuxième argument [TasksController, 'index'] indique le contrôleur et la méthode à utiliser pour répondre aux requêtes sur cette route.

Si votre contrôleur utilise les noms de méthodes standards, vous pouvez simplifier l’enregistrement de toutes les routes associées en une seule ligne de code comme suit :

Nous pouvons maintenant vérifier que toutes nos routes sont bien enregistrer via la commande suivante :

Cette commande permet de lister toutes les routes enregistrées
Cette commande permet de lister toutes les routes enregistrées

La validation des données

La validation des données est un aspect crucial dans le développement d’applications web. L’équipe d’AdonisJS a créé une bibliothèque de validation de données agnostique du framework appelée VineJS qui s’intègre parfaitement à AdonisJS. VineJS est l’une des bibliothèques de validation les plus rapides dans l’écosystème Node.js.

Nombre d'opérations par seconde
Nombre d’opérations par seconde

Vous n’êtes bien entendu pas obligé d’utiliser VineJS et opter pour d’autres librairies comme Zod par exemple.

Voyons comment VineJS fonctionne. Créons un validateur pour une tâche :

Intégrons à présent notre validateur dans le contrôleur pour assurer la conformité des données soumises lors de la création d’une tâche :

La variable payload est correctement inférée et contient les données validées issues de la requête. En cas de non-conformité, AdonisJS gère automatiquement les erreurs de validation, les convertissant en une réponse HTTP appropriée :

L’accès aux données

Dans AdonisJS, l’accès et la manipulation des données s’appuient sur Lucid, son ORM.

Pour illustrer l’utilisation de Lucid, nous allons reprendre notre exemple de tâche. Créons un modèle représentant une tâche avec les champs idtitledescription, et isCompleted dans une base de données :

Utilisons ensuite ce modèle dans notre contrôleur pour ajouter une tâche en base de données :

Lucid fournit bien entendu les opérations CRUD classique (Create, Read, Update, Delete) via plusieurs méthodes :

  • Create : Utilise Model.create pour insérer de nouvelles données;
  • Read : Model.find ou Model.findBy pour récupérer une entrée spécifique, et Model.all pour obtenir toutes les entrées;
  • Update : Utilise Model.query().where().update() ou met à jour une instance de modèle existante puis appelle save();
  • Delete : Utilise Model.query().where().delete() ou appelle delete() sur une instance de modèle.

Des ressources pour aller plus loin

Pour celles et ceux qui souhaitent approfondir leurs connaissances, voici quelques ressources précieuses :

  • Adocasts : Un large éventail de vidéos abordant une multitude de sujets relatifs à AdonisJS, idéal pour les personnes préférant l’apprentissage visuel;
  • Adonis mastery : Semblable à Adocasts, cette plateforme offre une richesse de contenus vidéo pour maîtriser AdonisJS;
  • Chaîne YouTube de Romain Lanz : Les vidéos de Romain Lanz, membre clé de l’équipe d’AdonisJS, sont hyper intéressantes avec des exemples concrets. Vous pouvez également le suivre en live sur Twitch;
  • Documentation officielle d’AdonisJS : Pour une compréhension approfondie, rien ne vaut la documentation officielle.

Ces ressources constituent un excellent point de départ pour explorer en profondeur les fonctionnalités et les capacités d’AdonisJS.

Pour finir…

On vient de voir un framework qui selon moi est le plus abouti et propose la meilleure expérience développeur de l’écosystème Node.js et mérite amplement d’être plus connu. J’espère qu’au travers de cet article, j’aurais attisé la curiosité de quelques un d’entre vous.

J’aimerais profiter de cet article pour vous encourager à rejoindre la communauté AdonisJS, quel que soit votre niveau d’expertise. Participer à un projet open source est une excellente façon d’apprendre et de contribuer à un projet significatif.

Il est bon de rappeler que ces projets sont souvent menés par des bénévoles. Leur engagement mérite notre reconnaissance et notre soutien. En contribuant, vous ne développez pas seulement vos compétences, mais participez également à un effort collectif pour offrir des solutions open source de qualité à la communauté.


Annonces partenaire

Je suis lead developer dans une boîte spécialisée dans l'univers du streaming/gaming, et en parallèle, je m'éclate en tant que freelance. Passionné par l'écosystème JavaScript, je suis un inconditionnel de Node.js depuis 2011. J'adore échanger sur les nouvelles tendances et partager mon expérience avec les autres développeurs. Si vous avez envie de papoter, n'hésitez pas à me retrouver sur Twitter, m'envoyer un petit email ou même laisser un commentaire.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.