Come strutturare in modo modulare un'app Node.js con ExpressJS

Modularizzare un'applicazione Node.js che utilizza ExpressJS è fondamentale per mantenere il codice pulito, scalabile e manutenibile. In questo articolo vedremo come organizzare un'applicazione Express in modo modulare, separando le responsabilità in diversi file e cartelle.

1. Struttura delle cartelle

Una struttura modulare consigliata può essere la seguente:


my-app/
├── app.js
├── routes/
│   ├── index.js
│   └── users.js
├── controllers/
│   ├── userController.js
├── models/
│   └── user.js
├── middlewares/
│   └── auth.js
└── config/
    └── db.js

2. Punto di ingresso: app.js

Il file app.js è il punto di partenza dell'applicazione. Qui configuriamo Express e montiamo le route.


const express = require('express');
const app = express();
const indexRoutes = require('./routes/index');
const userRoutes = require('./routes/users');

app.use(express.json());

app.use('/', indexRoutes);
app.use('/users', userRoutes);

app.listen(3000, () => {
  console.log('Server in ascolto sulla porta 3000');
});

3. Routing

Ogni file all'interno della cartella routes/ gestisce un gruppo specifico di endpoint.

routes/index.js


const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.send('Benvenuto nell\'API');
});

module.exports = router;

routes/users.js


const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');

router.get('/', userController.getAllUsers);
router.post('/', userController.createUser);

module.exports = router;

4. Controller

I controller contengono la logica applicativa per ciascuna route.

controllers/userController.js


const users = [];

exports.getAllUsers = (req, res) => {
  res.json(users);
};

exports.createUser = (req, res) => {
  const user = req.body;
  users.push(user);
  res.status(201).json(user);
};

5. Middleware

I middleware possono essere definiti separatamente per funzioni riutilizzabili, come l'autenticazione.

middlewares/auth.js


module.exports = (req, res, next) => {
  const token = req.headers['authorization'];
  if (token === 'segreto') {
    next();
  } else {
    res.status(401).json({ message: 'Non autorizzato' });
  }
};

6. Configurazione e modelli

Tutte le configurazioni (come la connessione al database) dovrebbero stare in config/, mentre i modelli di dati in models/.

config/db.js


const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/mydb', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

models/user.js


const mongoose = require('mongoose');

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

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

Conclusione

Strutturare un'app ExpressJS in modo modulare permette di avere un codice più chiaro, testabile e facile da estendere. Separare routing, controller, middleware e configurazione è una buona pratica che migliora la qualità del software, specialmente in progetti di medio-grandi dimensioni.

Torna su