NodeJS

Chargez des images avec NodeJS

Vous savez sans doute charger des images en PHP, mais savez vous le faire en NodeJS? On petu être perdu dans on aborde une nouvelle technologie. Nous allons voir comment le faire avec NodeJs. Le principe est un peu le même, on envoit un binaire via hTTP depuis la pageHTML, et côté serveur on récupère le fichier, mais là vous devez faire un peu plus de choses.

Le code de la page HTML

On fera au plus simple, un formulaire, avec une chose d’importance, l’envoi doit se faire en multipart/form-data. Qu’est ce que c’est? Lorsque vous avez un formulaire simple qui envoit des caractères alphanumériques, vous ne spécifiez pas le type d’envoi (enctype)

<form action="/submit" method="POST">
  <input type="text" name="username" value="example_user">
  <input type="text" name="age" value="30">
  <button type="submit">Submit</button>
</form>

Le format urlencode

En fait il y a un enctype par défaut qui est application/x-www-form-urlencoded, cela encode les données des champs sous forme de paire clé-valeur comme dans une url, ce qui le fait ressembler à un querystring. Les caractères spéciaux sont remplacé, par exemple le caractère space est remplacé par %20, les successions de paries clé-valeur sont liées par le signe esperluette « & ». Le request body est :

id=3&nom=antoine

C’est le mode préféré quand on n’a pas de fichier à uploader.

Ensuite si on veut envoyer des fichier binaires, on choisit l’enctype multipart/form-data.

Le format multipart/form-data

Utilisez ce format pour l’nevoi de fichiers. Si vous faites un envoi en multipar, observez le header envoyé, il a la forme suivante :

POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

Boundary veut dire limite ou frontière en anglais. Vos données envoyée se font par troçon délimité par la frontière.

Le request body est le suivant

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="username"

example_user
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="example.jpg"
Content-Type: image/jpeg

<binary content of the file>
------WebKitFormBoundary7MA4YWxkTrZu0gW--

Les données envoyée sont délimitées par la chaine « boundary=–« . On utilise ce mode quand il y a u nmix de texte et de fichier binaire.

Le format text/plain

username=example_user
age=30

Ce format est plus rare, et vous n’avez pas besoin de l’utiliser. Il envoit les données sans encoder

Mise en oeuvre du projet

Il va falloir installer NodeJs, avec la librairie multer our récupérer les binaires. Le fichiet HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>

<body>
    <div class="container">
        <h1>File Upload</h1>
        <form id='form'>
            <div class="input-group">
                <label for='name'>Your name</label>
                <input name='name' id='name' placeholder="Enter your name" />
            </div>
            <div class="input-group">
                <label for='files'>Select files</label>
                <input id='files' type="file" multiple>
            </div>
            <button class="submit-btn" type='submit'>Upload</button>
        </form>
    </div>
    <script src='./script.js'></script>
</body>

</html>

Le fichier JS front end

const form = document.getElementById("form");

form.addEventListener("submit", submitForm);

function submitForm(e) {
    e.preventDefault();
    const name = document.getElementById("name");
    const files = document.getElementById("files");
    const formData = new FormData();
    formData.append("name", name.value);
    for (let i = 0; i < files.files.length; i++) {
        formData.append("files", files.files[i]);
    }
    fetch("http://localhost:3000/upload_files", {
        method: 'POST',
        body: formData
    })
        .then((res) => console.log(res))
        .catch((err) => console.log("Error occured", err));
}

Le fichier style

/* style.css */
body {
    background-color: rgb(6, 26, 27);
}

* {
    box-sizing: border-box;
}

.container {
    max-width: 500px;
    margin: 60px auto;
}

.container h1 {
    text-align: center;
    color: white;
}

form {
    background-color: white;
    padding: 30px;
}

form .input-group {
    margin-bottom: 15px;
}

form label {
    display: block;
    margin-bottom: 10px;
}

form input {
    padding: 12px 20px;
    width: 100%;
    border: 1px solid #ccc;
}

.submit-btn {
    width: 100%;
    border: none;
    background: rgb(37, 83, 3);
    font-size: 18px;
    color: white;
    border-radius: 3px;
    padding: 20px;
    text-align: center;
}

Le fichier server.js

//https://blog.logrocket.com/multer-nodejs-express-upload-file/

const express = require('express');
const app = express();
const multer = require('multer');
// configuration de multer
const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'uploads/')
    },
    filename: function (req, file, cb) {
        cb(null, file.originalname)
    }
})
const upload = multer({
    storage: storage
})


const path = require('path');
app.use(express.static(path.join(__dirname, './')))


app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// app.post('/upload_files', (req, res) => {
//     console.log(req.body);
// })
app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
})

app.post('/upload_files', upload.array("files"), (req, res) => {
    console.log(req.files);
    console.log(req.body);
    res.json({ message: "Files uploaded successfully" });
})

app.listen(3000, () => {
    console.log("Server is running on port 3000");
})

J’ai fourni les scripts, je commenterai le fichier server.js puisque tout se joue dans ce fichier.

  • on utilise multer pour prendre en charge l’upload de fichier,
  • la variable storage paramètre le fonctionnement du multer, répertoire de sauvegarde des fichiers, nommage des fichiers
  • Pour servir index.html, on utiliser express.static, notez l’argument de path.join qui spécifie le répertoire du fichier index.html. express.static permet de servir les fichiers statiques (css, texte,html,javascript), il faut le dire explicitement.
  • app.use(express.urlencoded({ extended: true })); est un middleware, qui va attacher à req.body (le corps de la requête) la parsing des éléments envoyé par le formulaire avec un enctype=application/x-www-form-urlencoded. Concernant extended:true, c’est juste un choix de librairie de parsing, si à true, va utiliser la librairie qs qui supporte la récursivité des objets, alors que extende:false va utiliser la librairie querystring, qui ne supporte par la récursivité.
app.use(express.urlencoded({ extended: true}));
{
  "username": "JohnDoe",
  "details": {
    "age": "30"
  }
}

app.use(express.urlencoded({ extended: false }));
{
  "username": "JohnDoe",
  "details[age]": "30"
}

Facilitons nous la vie avec nodemon

J’utilise systématiquement nodemon pour redémarrer le serveur nodeJS quand il y a une modification de fichier, c’est très pratique pour développer, on n’ pas besoin de redémarrer manuellmenet à chaque fois en ligne de commande : node server.js, à la place on fait nodemon server.js.

La librairie multer

Il y a beaucoup plus d’option sur la librairie multer que je n’ai montré dans ce post, je vous renvois vers la documentation officielle de multer. Multer est un middleware d’express, qui permet de sauvegarder les fichiers binaires envoyés. Autres propriétés intéressant : mimetype, size, originalName, fileFilter pour filtrer les types de fichier.

Débugger une application NodeJs avec VSCode

Débug d’une application NodeJS exécutée dans une fenêtre VSCode

Aller dans Debug (icône avec un insecte), cliquer sur le triangle vert, puis sélectionner NodeJS. Mettre un point d’arrêt (Breakpoint). Une barre d’outil apparaît permettant de naviguer dans l’exécution pas à pas. C’est le mode de débug le plus simple (en dehor de console.log bien sûr).

Débug d’une application NodeJS initié depuis le navigateur en s’attachant au process

Il s’agit de s’attacher à un process avec VSCode. Clonez le projet :

https://github.com/gtsopour/nodejs-shopping-cart

Il vous faut faire un fichier de configuration launch.json:





Ensuite placez un breakpoint, et recharchez la page correspondante.

Débug en lançant le process

Lors qu clic sur le triangle vert, assurez vous d’être sur Launch Program.

Debug en remote (depuis la production par exemple)

Débugger quand c’est Typescript

https://code.visualstudio.com/docs/typescript/typescript-debugging

Installer une application NodeJs sur O2Switch

Mettre en place le projet NodeJS dans l’insterface O2Switch (CPanel)

Aller depuis l apage d’accueil de Cpanel, vers la section « Logiciels », choisir Setup Node.js App

Dans la page de configuration de votre application NodeJS, cliquer sur « Create Application »

Remplir le champs version de NodeJS, le mode de déploiement (Productionà, le chemin absolu vers la racine, le startup file corresond au fichier d’entrée de votre application, celui auquel vous faite node nom_fichier.js.

Une fois la configuration validée, vous verrez cet écran.

Comment organiser votre projet Node/Expresse/React Typescript?

La difficulté est que dans mon cas j’avais deux répertoires, frontend et backend. Imaginons que notre nom de domaine soit cloneflickr.jedeploiemonappli.com, la page d’accueil doit correspondre à la route ‘/’ dans Express. Cependant on a aussi une application ReactJS

fff

Connectez vous à Mysql pour un projet NodeJS Typescript

Si vous avez lu le premier article concernant le bootstrapping d’un projet Node Express Typescript, je n’ai pas encore parlé de la connection de la dernière pièce qui est la base de données. Dans cet article je vais parler de la connexion à une base MySQL.

Installation des composants mysql2

npm install mysql2

npm install typeorm reflect-metadata

Ici on installe un ORM, mais on ne va pas forcément l’utiliser.

Connexion à la base de données

Démarrer un projet ReactJS typescript avec ViteJS

Installation de viteJS avec npm

D’abord installons ViteJS

npm create vite@4.1.0

// alternative pour installer la dernière version

npm create vite@latest

// répondez aux questions
? Project name: » nom_projet

>   Vanilla
    Vue
    React
    Preact
    Lit
    Svelte
    Others


// on sélectionne React puis on a l'écran suivant
>   JavaScript
    TypeScript
    JavaScript + SWC
    TypeScript + SWC

Sélectionnons Typescript simple


√ Project name: ... cloneflicker
√ Select a framework: » React
√ Select a variant: » TypeScript

Scaffolding project in E:\projet\frontend\cloneflicker...

Done. Now run:

  cd cloneflicker
  npm install    
  npm run dev 

A la fin de la configuration de votre projet, un petit rappel de ses caractéristiques et une suggestion de commandes.

Au lancement on a l’écran suivant :

  VITE v4.5.5  ready in 13692 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h to show help

Vou spouvez CTRL + Click sur le lien pour lancer le site

Une des choses que vous allez remarquer le plus est la vitesse de lancement. C’est plus rapide qu’avec Webpack, la raison est que Vite optimise le build et ne construit pas tout, comme Webpack.

Structure du projet React Typescript

Le dossier public contient la page index.html qui va servir d’hôte à toute votre application React. Tandis que le dossier src contient tous les fichier de votre application React.

Le fichier tsconfig.json sert à configurer Typescript, le fichier vite.config.ts sert à introduire Vite,et n’oublions pas le fichier package.json.

Création de notre premier composant React en typescript !

Créons un fichier Message.tsx

function Message() {
    return <h1>Hello World</h1>;
}

export default Message;

Maintenant incorporons le dans App.tsx, effaçons le contenu par défaut de App.tsx pour simplifier notre construction.

import Message from './Message';

function App() {
  return <div>
    <Message />
  </div>
}

export default App

Au fur et à mesure que vous mettez à jour vos fichier, regardez la console, il y a le message

22:53:30 [vite] hmr update /src/App.tsx (x2)

Votre page s’est rafraichie.

Installation de Tailwind CSS

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

ça va générer deux fichiers de configuration tailwind.config.js et postcss.config.js. Remarquez que tailwindcss est une devDependency !

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Rajouter dans index.css ces lignes :

@tailwind base;
@tailwind components;
@tailwind utilities;

Modifier la class pour h1

function Message() {
    const name = 'Yvon';
    return <h1 className="text-4xl font-bold underline">Hello {name}</h1>;
}

export default Message;

Lancer l’application accessible via votre mobile

> npm run dev -- --host



  VITE v4.5.5  ready in 830 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: http://172.22.80.1:5173/
  ➜  Network: http://172.18.96.1:5173/
  ➜  Network: http://192.168.1.151:5173/
  ➜  press h to show help

Pour pouvoir utilise vite --host, il faut l’installer globalement.

Changer le répertoire de build pour vite

Par défaut vite build dans le répertoire dist. Ce répertoire sert pour la production, en phase de développement, il n’est pas généré. Pour avoir le build dans le répertoire build, il faut modifier vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  build: {
    outDir: 'build', // Spécifie ici le répertoire de sortie
  },
})

L’attribut build n’apparait dans le fichier originel.

Démarrer une application Node/Express Typescript

Bootstrapping du projet Node Express

Avec NodeJS, il existe plusieurs façon de faire une application web

#créer le répertoire de projet
mkdir nodeexpressts
# initaliser le projet en répondant oui à tout
npm init -y

npm init -y    // dit oui à tout
{
  "name": "nodeexpressts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
  // Ensuite créer un fichier index.js pour commencer
touch index.js
ouvrir VSCode dans ce répertoire projet
code .

On va installer Express

npm install express

On va code le fichier index.js

//index.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
    res.send('Hello World!');
});

app.listen(port, () => {
    console.log(`Example app listening on port ${port}!`);
});

Passons à Typescript !

Installation de Typescript

npm install typescript

Ensuite renommons le fichier index.js en index.ts !

En survolant les variable maintenant vous allez voir que pas mal de variable sont de type any, ça prouve qu’on est passé nen mode Typescript.

Installaton des fichier de type pour nodeJS et Express

npm install @types/express @types/node

modification des façons d’importer

Dans Typescript on n’utilise pas require mais import

import express, { Express, Request, Response } from 'express';
const app: Express = express();
const port = process.env.PORT || 3000;

app.get('/', (req: Request, res: Response) => {
    res.send('Hello World! in Typescript Now'); // modifié
});

app.listen(port, () => {
    console.log(`Example app listening on port ${port}!`);
});

A ce stade en survolant la varaible express, on voit que c’est typé.

Illustration, vous ne pouvez pas mettre n’importe quoi avec la notation pointée, si l’objet ne possède pas la méthode, vous aurez une erreur.

app.toto  << erreur souligné en rouge dans VSCode

Pour aller plus loin dans le typage et aider Typescript à savoir de quel type est une varaible on postfix avec les deux point

app.get('/', (req : Request, res : Response) => {
    res.send('Hello World!');
});

démarrage du serveur sour Typescript

Nous devons transpiler le Typescript en Javascript avant de démarrer le serveur. Invoquons tsc

npx tsc --init    // npx si on n'a pas tsc en global

Created a new tsconfig.json with:                                                                                       
                                                                                                                     TS 
  target: es2016
  module: commonjs
  strict: true
  esModuleInterop: true
  skipLibCheck: true
  forceConsistentCasingInFileNames: true


You can learn more at https://aka.ms/tsconfig

Un fichier tsconfig.json est apparu, pour configurer la manière dont Typescript sera transpilé par exemple. Nous devons indiqué où se trouvent les fichier Js de sortie, ouvrons ce fichier

"outDir": "./dist"

Pour transpiler taper simplement npx tsc ou tsc (si on a installé en global, vérifiez le)

tsc
un répertoire dist est apparu, regarez le contenu ce sont des fichiers JS.
Maintenant pour démarrer nodeJS

node dist/index.js

Faisons comme les pro, commetn avoir npm build par exemple

Ouvron spackage.json et configurons l’objet scripts:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc",
    "start": "node dist/index.js"
  },

Modifions le script

app.get('/', (req: Request, res: Response) => {
    res.send('Hello World! in Typescript Now WITH NPM RUN');
});

Et en ligne de commande faisons

npm run build
> nodeexpressts@1.0.0 build
> tsc
//puis
npm run start

Installons Nodemon ! (en devDependencies)

npm install -D nodemon

Maintenant ça va redémarrer à chaque fois qu’on va modifier un fichier.

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "tsc -w & nodemon dist/index.js"
  },

npm run dev

Le & simple va exécuter en background

Il se peut que ça ne marche pas, en effet le & tout seul n’est pas une commande Windows mais Linux. Remplacer par :

"dev": "tsc -w && nodemon dist/index.js

il est probable que ça ne marche pas non plus, car tsc -w (w comme watch) peut ne pas rendre la main à nodemon. Dans ce cas il faut installer concurrently

npm install concurrently --save-dev
    "dev": "concurrently \"tsc -w\" \"nodemon dist/index.js\""

C’est un peu lourd comme syntaxe mais ça devrait résoudre vos problèmes.

Nettoyer le dossier dist avec rimraf

Si on veut s’assurer que le dossier soit entièrement nettoyer, on va installer rimraf (comme rm -rf !)

npm i -D rimraf


puis on modifie package.json

    "build": "rimraf dist &&tsc",

Mettez un fichier dans dist puis exécutez npm run build, le fichier va disparaître. Modifions le script pour ajouter un prestart et preserve, (et renommer dev en serve), qui vont simplement nettoyer le répertoire dist.

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "rimraf dist &&tsc",
    "prestart": "npm run build",
    "start": "node dist/index.js",
    "preserve": "npm run build",
    "serve": "concurrently \"tsc -w\" \"nodemon dist/index.js\""
  },

En lançant npm run serve, c’est preserve qui est lancé en premier.

Ce tuto est inspiré de cette vidéo Youtube

Comprendre les sockets avec Socket.io

Qu’est qu’un socket?

Un socket est une interface de communication entre deux noeuds dans un réseau informatique. Plus concrètement, entre deux ordinateurs, et pour les développeurs web entre un serveur et un client, aka votre ordinateur et plus précisément le navigateur.

Côté serveur

On va pour simplifier utiliser Nodejs, avec un script en local on va pouvoir en quelques ligne mettre en oeuvre un socket grâce à la librairie socket.io

Côté client

Grâce à une librairie socket.io-client, on va pouvoir se connecter à un socket.

Quelle est la différence entre un socket et une requête AJAX?

Dans le monde du HTTP, une communication entre client et serveur ne dure qu’un instant, entre deux communications il n’y a rien. Vous faites une requête AJAX, le client initie une demande (Request), le serveur réponse avec un Response, et puis c’est fini.

Dans le cas d’un socket, une fois que le client initie une demande de connexion, la communication s’établie et dure tant que l’on n’a pas arrêté, elle ne s’arrête pas toute seule. Le socket sert à maintenir une connexion persistente, avec un flot continu de données de part et d’autre.

Le socket répond au besoin de recevoir contnuellement des données, une application comme une courbe de bourse en temps réel a besoin d’un socket, cela permet une mise à jour temps réel du cours de bourse. Bien sû on pourrait faire toute les secondes une requête AJAX, mais c’est très consommateur de données, de par la nature du protocole HTTP. Socket ne fait pas partie de la technologie HTTP.

Démarrer un projet avec socket.io

Créez un nouveau répertoire de projet, ouvrez le avec VSCode, ouvrez un terminal sous VSCode.

Créer un fichier package.json comme ci-dessous:

{
  "name": "app-socket",
  "version": "0.1",
  "description": "mon socket.io app",
  "dependencies": {}
}

Installez Express

Express est un framework pour NodeJS en MVC.

npm install express@4

Créez le fichier index.js

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);

app.get('/', (req, res) => {
  res.send('<h1>Hello world</h1>');
});

server.listen(3000, () => {
  console.log('listening on *:3000');
});

vous pouvez lancer le serveur NodeJS avec la commande:

node index.js

ça va initialiser un serveur qui écoute sur le port 3000 (par défaut pour NodeJS). Si dans votre navigateur, vous ouvrez l’url http://localhost:3000. Gardez un oeil sur le terminal de VSCode également.

Ajout d’un fichier HTML

Nous allons améliorer notre code avec une page HTML à servir

<!DOCTYPE html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }

      #form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
      #input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
      #input:focus { outline: none; }
      #form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }

      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages > li { padding: 0.5rem 1rem; }
      #messages > li:nth-child(odd) { background: #efefef; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form id="form" action="">
      <input id="input" autocomplete="off" /><button>Send</button>
    </form>
  </body>
</html>

Changez le code d’index.js

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

Relancez votre serveur avec node index.js

Note : Pour éviter de redémarrer à la main à chaque fois qu’il y a une mise à jour du code, je vous suggère d’installer nodemon, un démon NodeJS, qui va redémarrer le serveur automatiquement à chaque enregistrement de fichier.

npm install --save-dev nodemon  // installe en tant que dépendance de développement
// redémarrer le serveur
nodemon ./index.js localhost 3000

Intégration de socket.io

Maintenant on va allez voir les choses intéressantes, l’intégration de socket !

Il nous faut agir sur deux fronts, sur le serveur et sur le client. Il y a donc deux partie à la librairie socket.io. (nous sommes toujours en architecture client/serveur)

Socket.io côté serveur

npm install socket.io

et éditons le fichier index.js

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

// début de code de gestion du socket
io.on('connection', (socket) => {
  console.log('a user connected');
  socket.on('disconnect', () => {
    console.log('user disconnected');
  });
});

// fin de code de gestion du socket

server.listen(3000, () => {
  console.log('listening on *:3000');
});

Notez qu’on crée le serveur de socket en lui passant dans le constructeur le server NodeJS. « connection » est l’événement qui se déclenche lorsque la page dans le front end se charge pour la première fois et qu’un message donc est envoyé au serveur.

Socket.io côté client

Ajoutez le snippet dans le fichier HTML avant la fermeture de body

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io();
</script>

ça y est notre application web est équipée!

Maintenant ouvrez la page a port 3000, votre terminal nodeJS va afficher ‘a user connected’. Ce qui se passe c’est que lorsque la page est loadée, la librairie socket.io va envoyer un signal vers le serveur, qui intercepte le message. Si vous bne voyez rien, rafraichissez la page.

Construction de l’application de messagerie instantanée

Maintenant côté client, écrivons le code JS pour émettre les messages entrés au clavier, dans le formulaire:

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io();

  var form = document.getElementById('form');
  var input = document.getElementById('input');

  form.addEventListener('submit', function(e) {
    e.preventDefault();
    if (input.value) {
      socket.emit('chat message', input.value);
      input.value = '';
    }
  });
</script>

et côté serveur on va afficher le message, ajoutez le snippet suivant :

io.on('connection', (socket) => {
...
  socket.on('chat message', (msg) => {
    console.log('message: ' + msg);
  });
});

Tapez les messages dans le formulaire, observez les logs côté serveur.

Le broadcasting côté serveur

Intéressons nous maintenant sur comment le serveur va émettre un message pour tous les client connectés, à la manière d’une station radio, d’où le terme ‘broadcasting’. Il faut utiliser la méthode emit() de l’objet io. Modifiez le code :

io.on('connection', (socket) => {
    console.log('a user connected');

    socket.on('disconnect', () => {
        console.log('user disconnected');
    });

    socket.on('chat message', (msg) => {
        console.log('message du client: ' + msg);
        io.emit('retour', { propriete1: 'valeur 1', propriete2: 'valeur2' })
    });
});

Configurer VSCode pour débugger

Il ya plusieurs façons de débugger NodeJS avec VSCode, le plus simple (mais peut être le plus ennuyant) est d’utiliser l’auto Attach, dès qu’un process NodeJS est démarré, VSCode se met en écoute. On va utiliser cette méthode. Pour plus d’information sur les autres méthodes allez sur cette page.

Utiliser les dev tools pour visualiser les communication via le socket

Vous pouvez voir les connexion socket comme vous pouviez le faire avec les requêtes Ajax. Dans les devtools, allez dans l’onglet Réseau, cliquez sur WS dans les filtres (à côté de XHR, Images etc.

Dans l’onglet Réponse, vous pouvez voir en fait les allées et venues des messages.

Installer le framework Express pour nodeJS

Ce tuto montre comment bootstraper un projet NodeJS avec la base de donnée MySQL

Installation de NodeJS et NPM

Pour l’installation, il suffit de télécharger NodeJS (la dernière version) NPM sera disponible automatiquement.

Installation de Express

Express est un framework MVC fait pour NodeJS, c’est l’équivalent de Symfony pour le PHP. Créez un répertoire pour votre projet

npm init   // pour initialiser le package.json

Installation des packages pour le projet

npm i dotenv
npm i express
npm i mysql

Code minimal pour se connecter à la base de donnée:

On veut vérifier avant de continuer plus loin que la connexion se fait sans problème.

#index.js
const express = require('express')
const app = express()
require("dotenv").config()
var mysql = require('mysql');


app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

const DB_HOST = process.env.DB_HOST
const DB_USER = process.env.DB_USER
const DB_PASSWORD = process.env.DB_PASSWORD
const DB_DATABASE = process.env.DB_DATABASE
const DB_PORT = process.env.DB_PORT

var con = mysql.createConnection({
    host: DB_HOST,
    user: DB_USER,
    password: DB_PASSWORD,
    port: DB_PORT
});
con.connect(function (err) {
    if (err) throw err;
    console.log("Connected!");
});

Code générique pour requêter dans une table

var con = mysql.createConnection({
    host: DB_HOST,
    user: DB_USER,
    password: DB_PASSWORD,
    port: DB_PORT
});
con.connect(function (err) {
    if (err) throw err;
    console.log("Connected!");
});

Installer nodemon pour recharger au changement de fichier

npm install --save-dev nodemon
pour lancer avec nodemon à la place de node
./node_modules/.bin/nodemon index.js

Débugger sous NodeJS avec VSCode

VSCode est vraiment l’éditeur de code couteau suisse, son avantage est que s’il y a un langage même confidentiel, vous trouverez un plugin. Même s’il n’est pas le meilleur dans chaque catégorie, par exemple je trouve PHPStorm mieux pour le PHP, il est un très bon outil gratuit de surcroît.

Pour NodeJs, c’est un peu plus simple que pour Xdebug en PHP, il y ap lusieur façons de déclencher le débugger de NodeJS, on va voir l’auto déclenchement du débugger dès qu’un process node est en cours d’exécution.

Je suppose que vous ayez un fichier index.js, à exécuter via la commande shell, pour le lancer vous faites node index.js. Si vous ne l’avez pas fait vous pouvez démarrer un projet NodeJS.

Et là vous devrez avoir la barre de status orange, indiquant que le débug est actif.

Configuration de VSCode pour le debug automatique (Auto attach)

Pour activer l’auto attach, faites la combinaison de touche : SHIFT + CTRL + P, une boite de recherche va apparaitre, tapez « Toggle Auto Attach » pour trouver l’option et cliquez dessus.

Maintenant chaque fois que vous démarrez un process NodeJS, VSCode se met en mode debug.

Retour en haut