npm init -y
npm install express @prisma/client
npx tsc --init // va créer le fichier tsconfig.json
npx prisma --init //
Fetching latest updates for this subcommand...
✔ Your Prisma schema was created at prisma/schema.prisma
You can now open it in your favorite editor.
warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.
Next steps:
1. Run prisma dev to start a local Prisma Postgres server.
2. Define models in the schema.prisma file.
3. Run prisma migrate dev to migrate your local Prisma Postgres database.
4. Tip: Explore how you can extend the ORM with scalable connection pooling, global caching, and a managed serverless Postgres database. Read: https://pris.ly/cli/beyond-orm
More information in our documentation:
https://pris.ly/d/getting-started
A ce stade un fichier .env et un répertoire prisma a été créé. Le .env contient la chaine de connexion, par défaut c’est pour du postgres, mais on va changer en mysql. Il faut créer la base prisma_demo_ts avant de faire les opérations de migration.
Maintenant on va constituer un fichier de modèle pour créer les tables dans
Création des fichiers de migration et migration dans la même commande !
npx prisma migrate dev --name add-user-contact-table
Environment variables loaded from .env
Prisma schema loaded from prisma\schema.prisma
Datasource "db": MySQL database "prisma_demo_ts" at "localhost:3306"
Applying migration `20251018092422_add_user_contact_table`
The following migration(s) have been created and applied from new schema changes:
prisma\migrations/
└─ 20251018092422_add_user_contact_table/
└─ migration.sql
Your database is now in sync with your schema.
Le script index.ts
import express from 'express'
import { PrismaClient } from '@prisma/client'
const app = express()
const prisma = new PrismaClient()
app.use(express.json())
// GET all users
app.get('/users', async (req, res) => {
const users = await prisma.user.findMany()
res.json(users)
})
// POST new user
app.post('/users', async (req, res) => {
const { name, email } = req.body
const user = await prisma.user.create({ data: { name, email } })
res.json(user)
})
app.listen(3000, () => console.log('🚀 Serveur démarré sur http://localhost:3000'))
Si vous avez un message d’avertissement relatif à verbatimModuleSyntax, commentez la ligne dans tsconfig.json.
Pour lancer la compilation du fichier index.ts, désignez le répertoire de sortie des fichier JS, c’est dans tsconfig.json, la clé outDir doit être décommentée : « outDir »: « ./dist »,
// Créez un répertoire pour votre projet Prisma et entrez dedans
npm init -y
npm i prisma --save-dev
Créez la base de données
CREATE DATABASE prisma_demo;
// Dans le fichier .env mettre cette chaine de connexion
DATABASE_URL="mysql://root:password@localhost:3306/prisma_demo"
npm install @prisma/client
npx prisma init
✔ Your Prisma schema was created at prisma/schema.prisma
You can now open it in your favorite editor.
Next steps:
1. Run prisma dev to start a local Prisma Postgres server.
2. Define models in the schema.prisma file.
3. Run prisma migrate dev to migrate your local Prisma Postgres database.
4. Tip: Explore how you can extend the ORM with scalable connection pooling, global caching, and a managed serverless Postgres database. Read: https://pris.ly/cli/beyond-orm
Un répertoire prisma a été créé dans le projet. Dans le fichier schema.prisma mettez le code ci-dessous :
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
createdAt DateTime @default(now())
}
Ce modèle crée une table User avec :
id auto-incrémenté
email unique
name optionnel
createdAt avec la date de création
Faire la migration
npx prisma migrate dev --name init
Cela crée :
table User
Génère le client Prisma dans node_modules/.prisma/client
un fichier de migration
Execution du script d’exploitation de la base de donnée :
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
// Créer un utilisateur
const newUser = await prisma.user.create({
data: {
email: 'alice@example.com',
name: 'Alice',
},
})
console.log('Utilisateur créé :', newUser)
// Lire tous les utilisateurs
const users = await prisma.user.findMany()
console.log('Liste des utilisateurs :', users)
}
main()
.catch((e) => console.error(e))
.finally(async () => {
await prisma.$disconnect()
})
Ce script une fois exécuté va créer un utilisateur dans la base de données.
Visualiser la base de données avec Studio
npx prisma studio
Vue de Prisma Studio sur http://localhost:5555/
Syntaxe de l’ORM Prisma
// Trouver un user par email
const user = await prisma.user.findUnique({
where: { email: 'alice@example.com' },
})
// Mettre à jour un user
const updatedRecord = await prisma.user.update({
where: { id: 1 },
data: { email: 'yvon.huynh@hotmail.com' },
})
console.log('Updated utilisateur :', updatedRecord )
// Supprimer un user
// const deletedRecord = await prisma.user.delete({
// where: { email: 'yvon.huynh@gmail.com' },
// })
// console.log('Effacement utilisateur :', deletedRecord)
Récemment pour les besoin de développement d’une extension Chrome, j’ai cherché un moyen de rafraichir l’extension car le process de rafraichissement était un peu fastidieux. Il fallait aller dans le menu des extensions (chrome://extensions) et rafraichir en cliquant sur un bouton. Je voulais automatiser cette procédure comme le fait le plugin Liveserver.
Mettons nous dans le contexte d’une application avec front et back découplé. NodeJS/Express est le back avec une base de données, et le front par exemple est une application ReactJS. Toute l’application n’est que webservice, et l’on pourra tester l’application rien qu’avec Postman.
Ce dernier prend en charge l’authentification, grâce à la possibilité de stocker le token JWT et de le renvoyer à chaque requête.
Installation des packages NPM
Je suppose que vous avez déjà bootstrappé une application node/Express/Typescript, sinon allez visiter la page du lien. LEs paquet à installer sont jsonwebtoken, bcrypt et comme on travaille en typescript il faudra les fichier type pour l’autocomplétion. Je mets aussi mysql2 au cas où vous ne l’auriez pas installé.
Voici le code de la route (!) qui s’occupe de l’authentification
app.post('/api/auth', async (req: Request, res: Response) => {
const { email, password } = req.body
if (!email || !password) {
res.status(400).json({ message: "Email et mot de passe requis." });
}
try {
const [rows] = await pool.execute(
"SELECT id, email, password FROM utilisateurs WHERE email = ?", [email]
)
const users = rows as any[];
if (users.length === 0) {
res.status(401).json({ message: "Utilisateur inconnu." })
}
// vérification du mot de passe
const user = users[0]
const match = await bcrypt.compare(password, user.password);
if (!match) {
res.status(401).json({ message: "Mot de passe incorrect." });
}
// sinon on génère un JWT token
const token = jwt.sign(
{ id: user.id, email: user.email },
process.env.JWT_SECRET || "secretKey",
{ expiresIn: "24h" }
);
res.json({ token });
} catch (err) {
console.log(error);
res.status(500).json({ message: 'Erreur serveur' })
}
})
Je vous laisse mettre les imports qu’il faut. Aussi il vous faudra avoir la table utilisateurs pour
Requêter avec Postman.
Postman c’est comme un navigateur sans écran, en fait un navigateur est composé d’un écran et d’une antenne émettrice-réceptrice. Installez Postman, et démarrez votre serveur nodeJS, la route de l’authentification est http://localhost:3000/api/auth, faites une requête POST
Vous recevrez le JWT en réponse.
Stocker le JWT dans Postman
Copiez le token (sans les guillements et collez dans le champs avec à gauche la liste déroulante mis sur l’item Bearer Token.
Comprendre le fonctionnement du JWT
A chaque requêtes le serveur, en en-tête Authorization sera envoyé
requireAuth est un middleware, il va filtrer toutes les requêtes qui viennent d’un client, l’avantage du middleware est qu’on n’a pas besoin de faire la validation manuellement dans la route, c’est automatique. Je le mets dans le répertoire src/middleware
fichier middleware/auth.ts
import { Request, Response, NextFunction } from "express";
import jwt from "jsonwebtoken";
import dotenv from "dotenv";
dotenv.config();
// solution JWT Stateless simple
const JWT_SECRET = process.env.JWT_SECRET || "dev_secret";
;
const verifyJwt = <T = object>(token: string): T => {
return jwt.verify(token, JWT_SECRET) as T
}
export interface AuthRequest extends Request {
user?: any;
}
export const requireAuth = (req: AuthRequest, res: Response, next: NextFunction) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
res.status(401).json({ message: "Missing or invalid authorization header" });
return;//le simple fait de mettre return permet à authHeader de ne plus avoir de undefined possible (enlever le return pour montrer l'erreur)
}
const token = authHeader.split(" ")[1];
if (!token) {
return res.status(401).json({ message: "Token invalide" });
}
try {
const payload = verifyJwt(token);
req.user = payload;
next();
} catch (err) {
res.status(403).json({ message: "Forbidden, vous êtes authentifié mais n'avez pas accès à la ressource, problème de permission" });
}
}
si vous êtes depuis un moment dans le monde de Javascript NodeJs et autres framework front end, vous avez dû déjà croiser au moins 3 de ces 5 programmes.
Mais à quoi servent ils? Nous allons voir un par un ces gestionnaires de paquets.
NPM Node Package Manager
Il est né en même temps que Node JS. Très largement utilisé en général. Il permet d’installer, d’éxécuter un process (build par exemple)
NVM Node Version Manager
Il vous permet d’installer plusieurs version de NodeJS. Il vous permet de chcker la version de NodeJS
NPX Node Package Execute
Il est inclus avec NPM à partir de la version 5.2 de NPM. Le X comme execute permet à NPX d’exécuter des paquets. Oui mais NPM sait aussi exécuter un package, mais à condition qu’il soit installé en global. Si un paquet est installé en local, il est local au projet, càd dans le répertoire node_modules du projet.
C’est là que NPX prend la relève, ce dernier est capable d’exécuter un paquet. Il va d’abord chercher dans la variable PATH puis dans les fichiers binaire. S’il ne trouve pas, il est capable d’aller chercher sur Internet.
YARN Yet Another Resource Negociator (Facebook)
Yarn installe les paquets en parallèle, et donc il est plus rapide.
PNPM Performant NPM
PNMP utilise un endroit centralisé pour installer les paquets. Avec NPM vous pouvez installer un paquet en global ou en local.
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.
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)
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
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é.
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é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 :
Il vous faut faire un fichier de configuration launch.json:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}\\src\\server.ts",
"outFiles": [
"${workspaceFolder}/**/*.js"
]
}
]
}
Ensuite placez un breakpoint, et recharchez la page correspondante.
la clé « request » a pour valeur « launch« , le debugger est lancé quand vous exécutez le programme. Par contre si vous avez déjà démarré avec npm run dev, et que vous voulez débugger, il faudra rattacher le debugger au process, on associera la valeur « attach«
Dans ce cas le launch.json ressemblera à ça (pas de clé program !)
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
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.
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
Si vous préférez ne pas installer Tailwindcss, voici une alternative qui commence à bine être populaire au moment où j’écris ces lignes, c’est ShadCN. Selon la documentation d’installation de Shadcn, il faut installer quand même TailwindCSS, car le styling repose sur TailwindCSS
// installation de TailwindCSS
npm install tailwindcss @tailwindcss/vite
// vous serez amené à sélectionner un style
npm install @shadcn/ui
// pour ajouter un bouton, ceci va créer un fichier component.json, un répertoire
npx shadcn add button
// extrait du fichier component.json
....
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
...
// vous allez sans doute avoir une erreur avec Tailwindcss je ne sais pourquoi mais il doit réutiliser certaines choses, installez ce qui manque
@tailwind base;
@tailwind components;
@tailwind utilities;
Lors de l’installation de TailwindCSS, j’ai eu un soucis avec une version de Vite un peu ancienne, il fallait au moins la version de vite à 5.2 pour utiliser Shadcn. Plus d’information concernant component.json
npm install vite@^5.2.0
// mettre à jour la peer dependency de react puisque le projet React a été démarré avec ViteJS
npm install @vitejs/plugin-react@latest
// si tout s'est bien passé refaites la commande
npx shadcn add button
Vous aurez potentiellement un message d’erreur du type
No import alias found in your tsconfig.json file.
Visit https://ui.shadcn.com/docs/installation/vite to learn how to set an import alias.
Dans ce cas c’est le fichier tsconfig.json qu’il faut modifier, il faut dire à Typescript où sont les composants Shadcn.
// dans le section compilerOptions ajoutez ça :
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
// le "." indique que le point de départ de résolution de chemin commence par là où le fichier tsconfig.json se situe (qui est la base du projet)
//en faisant ça vous pourrez avoir de beaux chemin d'import
import { MyComponent } from '@/components/MyComponent'
// au lieu de
import { MyComponent } from '../../../components/MyComponent'
En refaisant la commande npx shadcn add button vous aurez un dossier component dans /src, et vous trouverez votre composant
Import du bouton généré
Vous ne pouvez sans doute pas encore importer correctement le bouton
// App.tsx
import { useState } from 'react'
import './App.css'
import { Button } from '@/components/ui/button'
function App() {
const [count, setCount] = useState(0)
return (
<div className="App">
<h1>Synapse Front</h1>
<Button>Click me</Button>
</div>
)
}
export default App
// configuration complémentaire
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
})
// tsconfig.json cette ligne permet le mapping des types Typescript pour node et vite
...
"compilerOptions": {
"types": [
"vite/client",
"node"
],
...
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.
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 .
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)
Si vous avez l’erreur suivante:
error TS18003: No inputs were found in config file 'E:/<chemin>/tsconfig.json'. Specified 'include' paths were '["**/*"]' and 'exclude' paths were '["E:/<chemin>/multiservice/dist"]'.
C’est que vous n’avez pas de fichier .ts (typescript) dans le projet, il faut renommer les fichier js en ts.
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, comment 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
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. Start est pour la production, serve est pour le développement.
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.
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
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 :
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 :
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.
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.