Technologies Web synchrones et multi-dispositifs
This project is maintained by aurelient
L’objectif du TP est de mettre en place “l’enveloppe” d’une application Web avec un serveur Node/Express léger en Typescript, et client React en Typescript. La “stack” que nous allons voir dans ce TP serait peu ou presque la même pour Angular ou Vue.
Nous allons voir :
Ce TP fera l’objet d’un premier rendu individuel et d’une note binaire (PASS/FAIL). Voir les critères d’évaluation en bas de la page.
Vous ferez le rendu sur la forge (ce mercredi 8/01).
🔓 Si vous êtes déjà familier de la stack ci-dessus, vous pouvez tester l’utilisation de Webpack à la place de Vite (voir le TP de l’année dernière).
Nous vous recommandons chaudement de vous servir d’un version manager
pour NodeJS comme Node Version Manager
NVM afin de pouvoir changer de version de Node facilement ou installer la dernière version long term support (LTS)
avec nvm install --lts
. Ce conseil s’applique à toutes les autres technologies peu importe le langage (venv pour python, sdkman! pour le sdk android, …)
Créez un projet git sur la forge dès maintenant. Remplissez le champ Tomuss associé.
Installer Node dans sa dernière version lts
et Express si ce n’est pas déjà fait. Si c’est le cas, pensez à les mettre à jour.
(Optionel) Selon votre OS, la version de node et d’Express que vous allez installer, il sera peut être nécessaire d’installer express-generator
qui gère le “cli” d’Express (la possibilité de l’invoquer depuis la ligne de commande). Installez le globalement avec npm ou yarn.
À la racine de votre projet, créez deux dossiers:
server
avec un dossier src
qui contiendra le code Nodejs + Express côté serveurclient
avec un dossier src
qui contiendra le code React côté navigateurCe sont deux projets distincts.
Pensez régulièrement à ajouter les fichiers qui n’ont pas à être versionnés à votre .gitignore (a minima : node_modules & dist), vous pouvez vous servir de gitignore.io pour en générer un via des tags (Visual Studio Code, nodejs, …)
Poussez le projet sur la forge.
On va en premier configurer le serveur.
Allez dans le dossier server
.
Créez un projet node (yarn init
), en le liant à votre dépôt Git sur la forge via le champs repository
du package.json
.
Pour pouvoir travailler avec Typescript, installez quelques dépendances supplémentaires:
# Ajoute typescript à votre projet
yarn add typescript ts-node express --dev
# Ajoute les types d'un module à typescript
yarn add @types/node @types/express
# Installe le compilateur Typescript de façon globale
npm i -g tsc
# Créé un fichier de configuration pour Typescript
tsc --init
Trouvez le fichier automatiquement généré tsconfig.json
:
outDir
et décommentez là pour mettre comme valeur ./dist
.rootDir
et décommentez là pour mettre comme valeur ./src
.package.json
, dans la partie scripts
, mettre:"scripts": {
"start": "tsc && node dist/index.js"
}
Voici l’architecture du projet express que nous allons créer:
| - dist
| - src
| | - index.ts
| | - routes
| | - hello.router.ts
| - package.json
| - yarn.lock
| - tsconfig.json
| - .gitignore
Dans notre index.ts
, nous allons créer le serveur:
import express from 'express';
import { HelloRouteur } from './routes/hello.router';
const app = express();
const port = process.env.PORT || 3000;
app.listen(port, () => {
process.stdout.write(`Server started on port: ${port}\n`);
});
app.use('/hello', HelloRouteur);
Dans hello.router.ts
, nous allons créer un des routeurs de notre API:
import express from 'express';
const helloRouteur = express.Router();
// With middlewares you can ensure the user is authenticated
// before requesting secured API routes
helloRouteur.use((request, response, next) => {
process.stdout.write('HelloRouter Middleware\n');
if (request.ip.endsWith('127.0.0.1')) {
process.stdout.write('Request from local IP\n');
next();
} else {
next();
}
});
helloRouteur.get('/', (request, response) => {
response.send('Hello TIW8 !');
});
export {
helloRouteur as HelloRouteur
};
Testez votre serveur avec la commande yarn start
Si vous avez des problèmes remontés par Typescript, cherchez à les résoudre. En comprenant ce que vous faites, en cas de doutes, on en parle en classe.
Vérifier que le serveur fonctionne et versionnez le sur la forge.
Allez maintenant créer un projet React dans le dossier client en utilisant Vite
Nous verrons plus en détail le fonctionnement de React lors de la prochaine séance. Pour le moment nous allons créer un projet simple.
Comme pour le projet serveur, il faut installer quelques dépendances avant tout:
yarn create vite client --template react-ts
Familiarisez vous avec le contenu créé, pour cela lire Getting Started de Vite et personnalisez le.
src/assets
et public
. Lire la documentation pour comprendre la différenceIl faut maintenant dire à Express où aller chercher le contenu.
Pour cela il faut lui dire que sa route /
est maintenant ../../client/dist/index.html
Rajouter les constantes suivantes (selon vos noms de fichiers et de dossiers) :
const path = require("path");
const DIST_DIR = path.join(__dirname, "../../client/dist");
const HTML_FILE = path.join(DIST_DIR, "index.html");
// TODO Modifier la route '/' pour qu'elle pointe sur HTML_FILE
Nous allons maintenant incorporer Tailwind CSS et une bibliothèque de composants associés, par exemple shadcn/ui ou des composants material design.
Restructurer l’application pour qu’elle utilise plusieurs composants. Le premier affichera le titre et les images. Le deuxième contiendra le compteur. Un dernier contiendra un Footer qui utilise un composant venant de shadcn/ui ou d’une bibliothèque de composant type Material.
On placera ces composants dans un dossier components
.
import React from "react";
import ReactDOM from "react-dom";
import Header from "./components/Header.tsx";
import Content from "./components/Content.tsx";
const Index = () => {
return (
<div className="container">
<Header />
<Content />
</div>
);
};
ReactDOM.render(<Index />, document.getElementById("root"));
Installez l’extension React Developer Tools dans votre navigateur préféré. Inspectez l’application.
Pour vérifier que votre code se conforme aux bonnes pratiques, nous allons utiliser eslint, et son plugin react.
Vite a normalement déjà créé un configuration eslint
sinon taper yarn run lint
Vous pouvez tester eslint à la “main” avec
yarn run eslint src/*.jsx
Si vous utilisez Prettier dans votre editeur de code, il est possible de rencontrer des conflits avec ESlint, si les deux n’appliquent pas les même règles. Prenez le temps nécessaire pour configurer les deux, cela sera utile pour tout le reste de l’UE.
Côté serveur, vous pouvez utliser ce guide pour configurer eslint pour node et typescript
--------------------------------------------------------------
| |
| ⚠️ A partir d'ici il est possible de travailler en binome 👨❤️👨 |
| |
--------------------------------------------------------------
La partie suivante peut se faire ne binome et avec l’aide de LLM
Les instructions ci-dessous n’utilisent pas docker. Si vous préférez utiliser docker, libre à vous, mais mon expérience avec est limitée, je répondrais donc en priorité aux questions sans docker.
Vous pouvez configurer votre VM pour utiliser un reverse proxy nginx qui pointera vers chacun de vos TPs.
Créer un compte gitlab-ci qui aura des droits limités
sudo adduser gitlab-ci
Créer le dossier ssh avec les droits appropriés.
sudo su - gitlab-ci
mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
exit
Sur votre machine locale créer un clé ssh. La clé privée sera stockée dans une variable GitLab CI SSH_PRIVATE_KEY
.
La clé publique sera ajoutée aux public key de l’utilisateur gitlab-ci:
echo "public-key-content" >> /home/gitlab-ci/.ssh/authorized_keys
Configurez les droits pour cet utilisateur puisse accéder au dossier de déploiement (le créer si ce n’a pas déjà été fait):
sudo chown gitlab-ci:gitlab-ci /var/www/tp1
Pour plus de sécurité on restraint les accès SSH dans /etc/ssh/sshd_config
en ajoutant les lignes suivants:
Match User gitlab-ci
PasswordAuthentication no
AllowTcpForwarding no
X11Forwarding no
Redémarrer les service ssh:
sudo systemctl restart sshd
Testez la connection ssh depuis votre machine. Tentez de déployer depuis votre machine comme vous allez le faire ensuite depuis la CI:
scp -r server/dist/* gitlab-ci@VOTRE_IP:/var/www/tp1
scp -r client/dist/* gitlab-ci@VOTRE_IP:/var/www/tp1
Corrigez au besoin votre configuration ngninx, ou votre processus de build pour que serveur et client soient bien trouvés.
Créer un GitLab CI pour votre utilisateur qui reprenne ces grandes lignes
Dans cet exemple seul le client est déployé, veillez à aussi déployer la partie serveur.
Veillez à ce que les variables soient bien définies, et votre VM bien configurée.
Le TP est individuel. Il est évalué sur une base binaire REUSSI/RATE et compte pour 10% de la note de Controle Continu (CC) totale. Il est à rendre pour mercredi 8/01 à 20h.
Les critères d’évaluation sont les suivants pour avoir un REUSSI (=20), si un des critères n’est pas rempli c’est un RATE (=0):
git clone
sans aucune modification de l’url TESTEZ le cloneyarn build
construit le projet côté clientyarn run start
lance le serveur.eslint
ne retourne pas d’erreur