Meilleures pratiques pour créer une application Express.js
Tags: backend, webdev, javascript, tutorial
Published: 2024-06-13 14:07:54

# Partie 2 : Meilleures pratiques et fonctionnalités avancées pour créer une application Express.js

#### Introduction

Pour la 1ère partie, je vous invite à visité l'article où j'ai parler de [l'introduction d'express et ses concepts fondamentaux](https://dev.to/land-bit/meilleures-pratiques-pour-creer-une-application-expressjs-583g).

Si c'est déjà fait, ici on va voir des notion un peu avancer.

Dans le monde du développement web, il existe une multitude de bibliothèques et de frameworks disponibles pour résoudre une variété de problèmes. Bien que nous abordions certaines des options populaires dans cet article, l'objectif n'est pas de vous prescrire des solutions spécifiques, mais de vous montrer les bonnes pratiques et les concepts qui peuvent être appliqués avec différentes technologies selon vos préférences et vos besoins. Que vous choisissiez Mongoose ou un autre ODM, Passport.js ou une autre solution d'authentification, l'important est de comprendre comment intégrer et utiliser efficacement ces outils pour créer des applications Express.js robustes et évolutives. Explorons maintenant comment structurer et améliorer vos applications Express.js.

#### 1. Structurer une application Express.js de manière organisée et évolutive

##### Architecture MVC (Model-View-Controller)

**Modèles :** Les modèles définissent les schémas de données et les interactions avec la base de données. Utilisez [Mongoose](https://mongoosejs.com/) pour [MongoDB](https://www.mongodb.com/), par exemple.

JavaScript
```javascript
// models/User.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    name: String,
    email: String,
    password: String,
});

const User = mongoose.model('User', userSchema);
module.exports = User;
```

**Vues :** Les vues gèrent les templates et le rendu des pages. Utilisez un moteur de templates comme [EJS](https://ejs.co/).

HTML
```html
<!-- views/index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home</title>
</head>
<body>
    <h1>Welcome, <%= user.name %></h1>
</body>
</html>
```

**Contrôleurs :** Les contrôleurs contiennent la logique des routes et des actions de l'application.

JavaScript
```javascript
// controllers/userController.js
const User = require('../models/User');

exports.getUser = async (req, res) => {
    const user = await User.findById(req.params.id);
    res.render('index', { user });
};
```

##### Organisation des fichiers et dossiers

Organisez vos fichiers et dossiers de manière structurée pour maintenir la clarté et la facilité de maintenance.

```
myapp/
├── config/
│   └── config.js
├── controllers/
│   └── userController.js
├── middlewares/
│   └── auth.js
├── models/
│   └── User.js
├── routes/
│   └── userRoutes.js
├── views/
│   └── index.ejs
├── app.js
└── package.json
```

##### Utilisation d'un outil de scaffolding

Utilisez des générateurs comme [Yeoman](https://yeoman.io/) pour créer la structure de base de l'application.

Shell
```sh
npm install -g yo generator-express
yo express
```

#### 2. Utiliser des modules et des bibliothèques tierces pour étendre les fonctionnalités d'Express

##### Mongoose pour MongoDB

[Mongoose](https://mongoosejs.com/) est un ODM (Object Data Modeling) pour [MongoDB](https://www.mongodb.com/) et [Node.js](https://nodejs.org/en).

JavaScript
```javascript
// app.js
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myapp', { useNewUrlParser: true, useUnifiedTopology: true });
```

##### Passport.js pour l'authentification

[Passport.js](https://www.passportjs.org/) permet d'implémenter facilement des stratégies d'authentification.

JavaScript
```javascript
// config/passport.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/User');

passport.use(new LocalStrategy(
  async (username, password, done) => {
    const user = await User.findOne({ username });
    if (!user) {
      return done(null, false, { message: 'Incorrect username.' });
    }
    if (!user.validPassword(password)) {
      return done(null, false, { message: 'Incorrect password.' });
    }
    return done(null, user);
  }
));
```

##### Socket.io pour les communications en temps réel

[Socket.io](https://socket.io/) ajoute des fonctionnalités de **WebSockets** pour les applications en temps réel.

JavaScript
```javascript
// app.js
const http = require('http');
const socketIo = require('socket.io');
const server = http.createServer(app);
const io = socketIo(server);

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

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

##### Helmet pour la sécurité

[Helmet](https://helmetjs.github.io/) aide à sécuriser l'application en configurant divers en-têtes HTTP.

JavaScript
```javascript
// app.js
const helmet = require('helmet');
app.use(helmet());
```

##### Morgan pour la journalisation

[Morgan](https://www.npmjs.com/package/morgan) est un middleware de journalisation des requêtes HTTP.

JavaScript
```javascript
// app.js
const morgan = require('morgan');
app.use(morgan('combined'));
```

#### 3. Gérer la sécurité des applications Express.js

##### Protection contre les attaques courantes

**Injection SQL :** Utilisez des ORM/ODM sécurisés et des requêtes paramétrées.

JavaScript
```javascript
// Using Mongoose to avoid SQL injection
const user = await User.findOne({ username: req.body.username });
```

**Cross-Site Scripting (XSS) :** Échappez les données de l'utilisateur et utilisez des bibliothèques comme `[xss-clean](https://www.npmjs.com/package/xss-clean)`.

JavaScript
```javascript
const xss = require('xss-clean');
app.use(xss());
```

**Cross-Site Request Forgery (CSRF) :** Utilisez des [tokens CSRF](https://dearsikandarkhan.medium.com/csrf-tokens-in-expressjs-node-js-web-framework-cc331069de2d) pour protéger les formulaires.

JavaScript
```javascript
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.use(csrfProtection);

// In your route
app.get('/form', (req, res) => {
    res.render('send', { csrfToken: req.csrfToken() });
});
```

##### Mise à jour des dépendances

Utilisez `npm audit` et `nsp` pour vérifier et corriger les vulnérabilités.

Shell
```sh
npm audit
```

##### Configurer HTTPS

Utilisez [Let's Encrypt](https://letsencrypt.org/) pour obtenir des certificats [SSL/TLS](https://www.ssl.com/fr/certificats/gratuit/) gratuits.

JavaScript
```javascript
const fs = require('fs');
const https = require('https');
const options = {
    key: fs.readFileSync('/path/to/key.pem'),
    cert: fs.readFileSync('/path/to/cert.pem')
};

https.createServer(options, app).listen(443);
```

#### 4. Déployer et mettre à l'échelle une application Express.js

##### Héberger sur des plateformes cloud

Des plateformes comme [Render](https://render.com/), [AWS](https://aws.amazon.com/fr/), [Heroku](https://www.heroku.com/), et [DigitalOcean](https://try.digitalocean.com/developerbrand/?_campaign=emea_brand_kw_en_cpc&_adgroup=digitalocean_exact_exact&_keyword=digitalocean&_device=c&_adposition=&_content=conversion&_medium=cpc&_source=bing&msclkid=f31cfe1fac4c12ea6f9498755d8d44f6&utm_source=bing&utm_medium=cpc&utm_campaign=emea_brand_kw_en_cpc&utm_term=digitalocean&utm_content=DigitalOcean%20Exact_Exact) facilitent le déploiement.

Shell
```sh
# Exemple de déploiement sur Heroku
heroku create
git push heroku master
```

##### Utilisation de [Docker](https://www.docker.com/)

Conteneurisez l'application pour un déploiement portable et reproductible.

```dockerfile
# Dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
```

##### Load balancing et scaling

Configurez un load balancer pour répartir le trafic et utilisez des outils comme [PM2](https://pm2.io/) pour gérer les processus Node.js.

Shell
```sh
# PM2
npm install pm2 -g
pm2 start app.js -i max
```

#### 5. Bonnes pratiques pour le développement avec Express.js

##### Tests unitaires et d'intégration

Utilisez [Mocha](https://mochajs.org/), [Chai](https://www.chaijs.com/) et [Supertest](https://www.npmjs.com/package/supertest) pour écrire et exécuter des tests.

JavaScript
```javascript
// test/user.test.js
const request = require('supertest');
const app = require('../app');

describe('GET /user', () => {
    it('responds with json', (done) => {
        request(app)
            .get('/user')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200, done);
    });
});
```

##### Documentation

Utilisez des outils comme [Swagger](https://swagger.io/) pour documenter les API.

JavaScript
```javascript
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
```

##### Optimisation des performances

**Mise en cache avec [Redis](https://redis.io/) ou [Memcached](https://www.memcached.org/) :**

JavaScript
```javascript
const redis = require('redis');
const client = redis.createClient();

app.get('/data', (req, res) => {
    client.get('data', (err, data) => {
        if (data) {
            res.send(data);
        } else {
            // Fetch data from database
            const newData = fetchDataFromDatabase();
            client.setex('data', 3600, newData);
            res.send(newData);
        }
    });
});
```

**Optimiser les requêtes à la base de données :**

Assurez-vous que vos requêtes sont optimisées et utilisez des index là où c'est nécessaire.

**Utiliser des middlewares de compression comme `[compression](https://www.npmjs.com/package/express-compression)` :**

JavaScript
```javascript
const compression = require('compression');
app.use(compression());
```

### Conclusion

En suivant ces bonnes pratiques et en utilisant des fonctionnalités avancées, vous pouvez créer des applications Express.js robustes, sécurisées et évolutives. La structuration de votre code, l'utilisation de modules tiers, la gestion de la sécurité, le déploiement efficace et les tests rigoureux sont essentiels pour développer des applications performantes et maintenables. Continuez à explorer et à intégrer ces pratiques dans vos projets pour améliorer constamment la qualité de vos applications.

**Voici quelques ressources supplémentaires qui pourraient vous aidez à continuer votre apprentissage :**

* **[La documentation officielle d'Express.js sur les bonne pratiques de la securité en production](https://expressjs.com/en/advanced/best-practice-security.html)**
* **Tutoriels et articles sur Express.js :**
    * **[MDN : Introduction à Express.js](https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction)**
    * **[Déployer une application Node.js avec Kinsta](https://www.youtube.com/watch?v=JBbyMn7dNys)**
    * **[Learn Node.js and Express with This Free 8-hour Back End Development Course](https://www.freecodecamp.org/news/free-8-hour-node-express-course/)**
* **Livres sur Express.js :**
    * **"Learning Express" de Carlos Rios**
    * **"Building Node.js Applications" de Ryan Tozier et Ashish Goel**
* **Rejoignez la communauté Express.js :** Participez à des forums et des groupes en ligne pour poser des questions, partager vos expériences et apprendre des autres développeurs.
* **Construisez vos propres applications :** La meilleure façon d'apprendre est de mettre la main à la pâte. Commencez par créer des applications simples et progressez vers des projets plus complexes.

**N'oubliez jamais que l'apprentissage est un processus continu. Restez curieux, explorez et créez, et vous deviendrez un maître du développement d'applications Express.js !**