Introduction à Node.js
Dans cette partie, nous allons étudier comment créer une application Full Stack en Javascript
(backend + frontend) en utilisant le langage Javascript.
Pour créer notre serveur web en Javascript, nous allons mettre en oeuvre un ensemble d'outils dont la
base est constitué du runtime Node.js.
Installation de Node.js
L'installation de Node.js est assez simple du fait qu'il existe un runtime déstiné à de nombreux systèmes
d'exploitations.
Il suffit de vous rendre sur le site officiel
Node.js, et de suivre les instructions d'installation
(téléchargement, etc.) correspondantes à votre système.
Pour vérifier l'installation, vous pouvez ensuite aller dans un terminal
et entrer l'instruction suivante : node --version
.
Si tout est bien installé, vous devez alors voir s'afficher l'information correspondante.
Initialisation de projet Node.js
Dans une approche Full Stack Javascript, les parties backend (code serveur)
et frontend (code client) sont en général séparées.
Cependant, de manière à apprendre à maitriser les outils liés à Node.js, nous allons dans un premier temps
nous concentrer sur la construction d'un backend plus "classique" qui contiendra les fonctionnalités
offertes par le serveur, mais aussi une partie cliente.
Création d'un projet
Commencez par créer un projet (un dossier dont vous choisirez le nom) dans lequel vous créerez
un sous-dossier nommé backend destiné à recevoir notre code serveur.
NB1 : il n'est pas obligatoire de créer un sous-dossier backend
dans le projet,
mais cela permet de bien séparer la partie serveur (dans backend/
)
d'une éventuelle partie cliente (qu'on mettra plus tard dans un sous-dossier par exemple
nommé frontend/
).
NB2 : dans les exemples ci-après, j'ai nommé mon projet/dossier fsjs_demo
Initialisation
L'installation de Node.js a (en plus de la commande node
) permis d'installer
le gestionnaire npm
qui va nous être très utile pour ajouter de nombreuses fonctionnalités
sous la forme de packages.
Dans un terminal, rendez-vous dans le dossier backend et exécutez la commande npm init
.
L'invite de commande pose alors plusieurs questions utilisées pour configurer le projet :
Vous pouvez laisser la plupart des valeurs par défaut (appuyez simplement sur la touche entrée),
mais par convention, vous changerez la valeur de entry point
en indiquant server.js
.
NB : le fichier server.js
n'existe pas encore -> nous allons le créer et c'est lui qui fera
office de point de démarrage de l'exécution de notre serveur web.
Une fois la commande exécutée, vous devez trouver dans le dossier backend
un nouveau fichier
nommé package.json
qui reprend les informations que vous avez entrées.
Ce fichier est très important car c'est lui qui contiendra (entre autres) les informations de dépendances
des packages utilisés dans le projet.
Nous reviendrons plus tard sur les informations principales contenues dans ce fichier.
L'exemple ci-dessous illustre un projet nommé fsjs_demo
après initialisation :
Serveur Basique
Pour démarrer notre serveur web, il nous faut maintenant créer le point d'entrée principal correspondant
au fichier server.js
(dans le dossier backend
).
Le contenu de ce fichier va très vite de complexifier, mais il est intéressant de créer un serveur très
basique pour comprendre les bases du fonctionnement de Node.js.
server.js
// Définition du n° de port sur lequel le serveur va écouter
// (ce sera la valeur système process.env.PORT si elle existe, 3000 sinon)
const port = process.env.PORT || 3000
// Inclusion du module prédéfini de Node.js permettant d'exécuter un serveur http
const http = require('http')
// Ce serveur très simple reverra toujours la même réponse :
// - un code http 200
// - un header spécifiant l'encodage de la réponse
// - le message "Le serveur Node.js dit <b>bonjour</b>"
const server = http.createServer((req, res) =>{
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html;charset=utf-8');
res.end("Le serveur Node.js dit <b>bonjour</b>")
})
// Démarrage de l'écoute des requêtes sur le port indiqué
server.listen(port,()=>{
console.log(`Le server écoute sur http://127.0.0.1:${port}/`);
})
Il ne reste plus qu'à exécuter ce script au sein de Node.js pour lancer le serveur :
Dans un terminal, dans le dossier backend
, entrez la commande : node server.js
Ouvrez un navigateur à l'adresse qui a été affichée dans la console à l'exécution du listen
:
vous devriez voir la réponse du serveur "Le serveur Node.js dit bonjour".
En affichant les informations réseau, vous verrez aussi le status code 200
(OK) envoyé par
le serveur pour indiquer au navigateur qu'il a bien pu traiter cette requête.
Vous pourrez remarquer que (pour l'instant) la réponse du serveur (représentée par l'objet res
dans le callback de l'appel à la méthode createServer
) est identique quelle que soit la route
demandée par votre navigateur : par exemple, si votre serveur tourne à l'adresse
http://127.0.0.1:3000
, la réponse reçue est la même qu'avec un chemin plus complexe comme
http://127.0.0.1:3000/truc/machin/chose
.
Ceci est dû au fait que dans l'appel à la méthode createServer
, notre code indique
au serveur d'envoyer la même réponse (res
) quelle que soit la requête req
reçue : le paramètre req
qui contient les informations relatives à cette requête
n'est d'ailleurs même pas utilisé.
NB : ce serveur est très basique -> nous verrons bientôt comment faire mieux ;).
Pour arrêter le serveur : CTRL+C
dans le terminal.
Scripts
L'environnement Node.js permet de spécifier des scripts correspondant à des tâches spécifiques liées
au projet : ces scripts peuvent être définis sous la clé scripts
du fichier package.json
.
D'ailleurs, dans le fichier que nous avons généré avec npm init
, on peut voir un script nommé
test
qui a été automatiquement généré et affiche un message dans la console s'il est lancé.
Pour exécuter un script, on utilise la commande npm run nom_du_script
Vous pouvez essayer d'exécuter le script test
en lançant npm run test
:
vous verrez alors le message indiquant qu'aucun test a été défini.
Pour créer un script de démarrage de notre projet, il suffit d'ajouter une ligne sous la clé
scripts
de package.json
.
Dans l'exemple ci-dessous, nous avons ajouté un script start
contenant le code de lancement
du serveur :
Pour l'utiliser, il suffit de lancer la commande : npm run start
.
NB : un script nommé start
est un cas un peu particulier du fait que pour le lancer,
on peut aussi simplement écrire npm start
.
Nous verrons par la suite que ce mécanisme de scripts est bien utile lorsqu'on veut par exemple
mettre simplement en oeuvre plusieurs manières de démarrer le serveur
(mode développement, mode production, etc.).
Package/module : nodemon
Petite expérience : modifiez la réponse de votre serveur en changeant le message renvoyé
par exemple :
"Le serveur Node.js dit bonjour" -> "Le serveur dit YO !!!"
Si vous rechargez directement la page dans votre navigateur, vous verrez que le message n'a pas changé.
Pour que le serveur change de comportement, il faut le redémarrer !
Cela signifie qu'à chaque modification de votre code, vous devez aller dans la console, faire
un CTRL+C
, et relacer la commande node server.js
: c'est fastidieux !
Heureusement, le package/module nommé
nodemon
facilite grandement le développement en redémarrant automatiquement le serveur node à chaque modification de son source.
Installation
Pour installer
nodemon (uniquement dans le projet) :
npm install nodemon
.
NB: depuis la version 5 de Node.js, il n'est plus nécessaire d'ajouter l'option --save
.
npm install ...
crée/complète dans backend
un nouveau fichier package-lock.json
:
il ne nous intéresse pas et vous ne devez pas y toucher !
npm install ...
crée/complète dans backend
le dossier node_modules
:
ce dossier contient l'ensemble des package que vous installe(re)z avec npm
:
vous ne devez pas y toucher !
Par contre, vous pouvez aller voir ce qui s'y trouve : vous remarquerez en particulier le dossier
.bin
qui contient la commande nodemon
-> c'est cette commande qui va nous
permettre de démarrer le serveur sans avoir à le relancer manuellement à chaque modification.
npm install ...
complète le fichier package.json
en y indiquant les dépendances du
projet. Cette fonctionnalité particulièrement dans le cas où vous souhaitez (ré)installer
les packages : vous pouvez supprimer le fichier package-lock.json
et le dossier
node_modules
-> la commande npm-install
utilisera le fichier
package.json
pour tout réinstaller automatiquement.
Exécution
Pour utiliser nodemon, vous pouvez entrer : node_modules/.bin/nodemon server.js
Ceci a pour effet de lancer le serveur (comme avec node server.js
), mais maintenant,
chaque modification du code source relance automatiquement le serveur !
(NB : il faut quand même rafraichir la page du navigateur).
Pour arrêter le serveur : CTRL+C
dans le terminal.
NB : il est aurait été possible d'installer nodemon
de manière globale
(rendant la commande directement accessible en ligne de commande pour tous vos projets) grâce
à npm install -g nodemon
.
Cependant, pour que cela fonctionne, vous devez avoir les droits d'écriture dans les dossiers d'installation
de Node.js, ce qui n'est pas le cas dans les salles de TP.
Nous venons de voir qu'il est possible de lancer l'exécution du serveur de plusieurs manières :
avec node
pour une "simple" exécution, et avec nodemon
pour une exécution
avec redémarrage automatique en phase de développement.
Pour simplifier ces tâches, nous allons créer différents scripts dans
package.json
:
NB1 : dans le script, on n'indique pas le chemin complet vers node_modules/.bin/nodemon :
npm
ira automatiquement le chercher dans le répertoire d'installation.
NB2 : on aurait tout à fait pu choisir un autre nom que "start-dev" pour le script.
Pour lancer le serveur en développement avec nodemon, il suffit maintenant d'exécuter :
npm run start-dev
.
Dans les scripts précédents, vous avez du remarquer que nous utilisons le code suivant pour définir
le port sur lequel tourne notre application :
const port = process.env.PORT || 3000
Comme indiqué précédemment, ce code 'tente' d'utiliser la valeur système process.env.PORT
pour
déterminer sur quel port démarrer le serveur.
Le module
dotenv sert à charger les variables d'environnement définies dans un fichier
.env
pour les rendre accessibles dans process.env
.
Installation
Pour ajouter le module
dotenv au projet :
npm install dotenv
.
Mise en oeuvre
Les variables d'environnement sont définies dans un fichier qu'on appelle par convention .env
.
L'exemple ci-dessous défini la variable PORT
que nous voulons utiliser :
.env
PORT=4000
Le chargement des variables est alors effectué dès le démarrage de l'application (par exemple au tout
début de server.js
) grâce à l'instruction :
require('dotenv').config({ path: './.env'} ) ;
On peut ensuite accéder à cette variable dans toute l'application au travers de process.env
Ci-dessous le nouveau fichier server.js
obtenu
server.js
// Charge les variables d'environnement définies dans .env
require('dotenv').config({ path: './.env'} ) ;
// Définition du n° de port sur lequel le serveur va écouter
const port = process.env.PORT || 3000
const http = require('http')
const server = http.createServer((req, res) =>{
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html;charset=utf-8');
res.end("Le serveur Node.js dit <b>bonjour</b>")
})
// Démarrage de l'écoute des requêtes sur le port indiqué
server.listen(port,()=>{
console.log(`Le server écoute sur http://127.0.01:${port}/`);
})
Vous constaterez maintenant que votre serveur tourne sur le port 4000 au lieu du port 3000 comme c'était
le cas auparavant.
NB : nous verrons dans la suite de ce cours que le fichier .env
peut contenir d'autres données
cruciales comme les informations de connexion à une base de données, une
clé de chiffrage, etc.
... et c'est pour cette raison qu'il est conseillé d'ajouter la ligne **/.env
à votre fichier
.gitignore
.