Comment structurer son code avec Node.js

Démarrer un nouveau projet est super excitant. En plus, avec Node.js, on peut arriver très rapidement a un prototype fonctionnel prêt à être déployé. Par contre, lorsque l’on part de zéro, on peut perdre beaucoup de temps à structurer son code.

Je vous partage ici quelques trucs que j’ai développés après avoir créé et contribué à plus d’une centaine de projets en javascript.

Aperçu de la racine

La structure de presque tous mes projets ressemble à celle-ci.

bin/
data/
lib/
test/
index.js
package.json
README.md

Regardons-là en profondeur…

1 — README.md

Le contenu d’un bon README serait l’objet d’un billet de blogue complet. Pour commencer, vous pouvez décrire le projet en quelques lignes, le nom des collaborateurs ainsi que les technologies utilisées.

L’extension .mdest utilisée pour le Markdown. Les sites de collaboration comme Github et Gitlab vont automatiquement le transformer en HTML avec de beaux styles prédéfinies.

2 — package.json

Pour utiliser le gestionnaire de paquet de node (NPM), il faut que votre projet ait ce fichier à sa racine. Ce fichier décrit votre projet, ses dépendances et quelques commandes pratiques que l’on va voir un peu plus bas.

Bonne pratique :npm init est la commande qu’il faut utiliser dans le répertoire de votre projet pour lancer un assistant qui va créer ce fichier pour vous.

3 — index.js

Il s’agit du fichier principal de votre application.

Bonne pratique : si le code du projet rentre au complet dans un seul fichier (dans le cas d’une petite librairie), il peut être contenu dans ce fichier, sinon, ce fichier ne doit qu’exposer (ou exporter) la partie publique de la librairie.

Bonne pratique : s’il s’agit d’un application web avec express, le fichier index.js ne devrait que rassembler les routes et les middlewares.

Exemple de fichier index.js qui exporte une app avec express:

const express = require('express');
const app = express();
app.get('/', function (req, res) {
res.send('Hello World!')
})
exports = app;

Notez que le fichier index.jsne démarre pas l’application (app.listen() ) mais ne fait que créer les routes et exporter l’app.

Pourquoi? Car cela permet de créer des applications modulaires. Si on ne démarre pas le serveur dans index.js (comme on le voit souvent), on peut utiliser l’application comme un librairie tierce en la montant comme simplement comme un middleware.

4 — bin

En programmation, il est commun de placer les exécutables d’un projet dans le dossier bin (pour binaire). Par exemple, le dossier /usr/binsous linux.

Dans le cas de Node.js, le code n’est pas compilé en binaire mais il y a un petit truc pour le rendre exécutable :

#!/usr/bin/env node

En plaçant cette ligne en haut de votre fichier javascript, vous indiquez à votre environnement que ce fichier doit être exécuté avec node.

4.1 — bin/start

Il s’agit de la commande pour démarrer votre application ou votre serveur.

Exemple qui exécute le fichier index.js ci-dessus :

#!/usr/bin/env node
const server = require('..');
server.listen(process.env.NODE_PORT || 8080);

Observons ces lignes. La première, comme on l’a vu plus haut, indique d’exécuter ce fichier avec node.

La deuxième ligne va chercher notre fichier index.js principal qui correspond à notre application.

Rappel 1 : sous linux, . correspond au dossier courant et .. est le dossier parent.

Rappel 2 : lorsqu’un fichier se nomme index.js il peut être omit. Par exemple require('..') est la même chose que require('../index.js') .

Et finalement, s’il s’agit d’une application web alorson peut la démarrer sur un port fourni en environnement ou 8080 par défaut.

$ NODE_PORT=80 ./bin/start

4.2 — Autres exemples de scripts bin

bin/test pour tester votre app
bin/demo pour charger des donnés d’une démo dans la BD
bin/sass pour compiler les assets avec sass

5 — data

Il s’agit d’un fourre-tout pour mettre vos données. Cela peut être un dump de la base de donnée ou encore des fixtures à utiliser comme des liste de pays et de langues.

Par exemple, dans mon app findzap, j’ai exporté les points d’accès Wi-Fi des sites web de ZAP de chacune des régions du Québec dans /data.

6 — lib

Ce dossier contient tout le reste du code de votre app. On voit souvent aussi le nom src comme alternative. Personnellement, j’aime mieux lib car cela exprime le fait que le code est modulaire et réutilisable (comme le format d’une librairie).

libn’a pas de fichierindex.js à sa racine, seulement des sous-dossiers.

Généralement, j’aime bien que les sous-dossiers représente des ressources comme ceci :

lib/articles/
lib/tags/
lib/users/

Ensuite, chacun de ces sous-dossiers contient un fichier index.js pour pouvoir importer facilement une ressource comme ceci :

const users = require('../users');
app.get('/users', function (req, res) {
res.send(users.all());
})

7 — test

Il s’agit de l’endroit pour mettre vos tests. Le plus simple est d’utiliser mocha.

Pour ce faire, installez mocha en globalnpm install --global mocha et de lancez la commandemocha test .

Bonne pratique : Recréer la même structure dans test que dans lib comme ceci :

Le fichier /test/users/index.js contient les tests pour /lib/users/index.js

# /test/users/index.js
const assert = require('assert');
const users = require('../lib/users')
describe('users',  () => {
it('should create a new user', () => {
assert.ok(users.create({ name: 'Nicolas' }));
})
})

Mot de la fin

Il y a un nombre infinie de structures et cela va selon les goûts de chacun. Le style que je présente ici est assez répandu dans la communauté open-source avec quelques variations.

Au final, ce qui compte est que vous vous y retrouviez et que vous ne perdiez pas de temps pour commencer à coder!

Like what you read? Give Nicolas Lupien a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.