NodeJS

Last Updated on 2 anni | Published: 11/10/2024

Node.js

Node.js è un ambiente di runtime open-source, multipiattaforma e basato su JavaScript che permette di eseguire codice JavaScript al di fuori di un browser. Creato nel 2009, Node.js si basa sul motore V8 di Google, lo stesso che alimenta il browser Chrome, il che garantisce elevate prestazioni e velocità.

A differenza dei linguaggi server-side tradizionali come PHP o Java, Node.js adotta un’architettura orientata agli eventi e non bloccante (non-blocking I/O), che consente di gestire un numero elevato di connessioni simultanee senza rallentare l’applicazione. Questo lo rende ideale per applicazioni in tempo reale e ad alte prestazioni, come chat, giochi online, server di streaming, API RESTful e molto altro.

  • Performance e velocità: Node.js esegue codice in modo asincrono grazie all’uso del single-thread event loop, ottimizzando l’uso delle risorse del server e riducendo i tempi di risposta.
  • Un linguaggio per il frontend e il backend: Usare JavaScript su entrambi i lati (client e server) offre una coerenza nello sviluppo e facilita il lavoro in team, poiché gli sviluppatori non devono imparare più linguaggi.
  • Ecosistema vasto e supportato: Con NPM (Node Package Manager), Node.js dispone di un’enorme quantità di librerie e moduli open-source che consentono di sviluppare applicazioni velocemente.
  • Scalabilità: Le applicazioni basate su Node.js sono progettate per essere scalabili. Grazie all’approccio asincrono e alla capacità di gestire molteplici richieste, Node.js si presta bene per applicazioni distribuite e scalabili orizzontalmente.
  • Community attiva: Node.js ha una vasta e crescente comunità di sviluppatori, che contribuisce a migliorare il framework con aggiornamenti, correzioni di bug e nuove funzionalità.
Node.js viene utilizzato in molteplici scenari, tra cui:
  • Server web: grazie alla sua velocità e efficienza nella gestione delle richieste.
  • Microservizi: perfetto per architetture moderne, Node.js permette di creare piccoli moduli indipendenti che collaborano per formare un sistema più grande.
  • Applicazioni in tempo reale: come le chat o i giochi multiplayer, dove la comunicazione rapida tra client e server è fondamentale.
  • API REST e GraphQL: per la creazione di server backend veloci e leggeri.

Per creare progetti Node.js bisogna innanzitutto installarlo sul proprio computer. L’ installazione include anche npm (Node Package Manager), che è il gestore dei pacchetti per Node.js, utile per installare dipendenze e librerie esterne.

Quando si installano i moduli di Node.js questi vengono memorizzati in diverse posizioni a seconda del tipo di installazione (locale o globale) e del sistema operativo.

Per avere una installazione locale utilizziamo npm install modulo.

I pacchetti vengono installati localmente, ovvero nella cartella del progetto in cui stai lavorando. Più precisamente, i moduli vengono salvati nella sottocartella node_modules, che si trova nella directory corrente del progetto.

Quando invece vogliamo installare i moduli a livello globale possiamo utilizzare npn install -g modulo. I pacchetti vengono installati globalmente, il che significa che puoi usare il modulo da qualsiasi progetto o posizione nel sistema. La posizione nel file system  per il sistema windows è :

C:\Users\TuoNomeUtente\AppData\Roaming\npm\node_modules

Detto questo da terminale o prompt possiamo creare la cartella che deve contenere il progetto (Ex: Clienti) e le relative dipendenze. Il progetto deve essere inizializzato con  il comando npm init. Verranno chieste alcune informazioni sul progetto, come il nome, la versione, la descrizione, il file di ingresso (solitamente index.js), e altro. Se invece vogliamo accettare i valori predefinidi possiamo utilizzare il comando npm init -y

Inizializzando il progetto si crea anche un file di configurazione package.json, molto simile al file seguente:

In questo file possiamo notare la chiave “type“:”module“ necessaria      per  abilitare        l’  importazione   dei    moduli  ECMA Script (ESM), che da codice nel caso del modulo express è:  import express from ‘express‘, inoltre possiamo anche notare che al progetto è stata fornita la dipendanza “express“. Inoltre attraverso la chiave “main“:”index.js“ definiamo il punto di ingresso dell’ applicazione.

Vediamo come implementare il file index.js per utilizzare il framework express che semplifica la creazione di applicazioni web e API, permettendo agli sviluppatori di gestire le richieste HTTP in modo più semplice e organizzato rispetto all’utilizzo del solo Node.js.

  • Express ci permette di definire le rotte che corrispondono a specifiche URL e gestire cosa fare quando gli utenti visitano quelle pagine.
  • Ogni volta che qualcuno visita una pagina web, viene fatta una richiesta HTTP. Express gestisce queste richieste e manda indietro una risposta.
  • I middleware sono funzioni che vengono eseguite in sequenza durante la gestione di una richiesta. Possono modificare la richiesta o risposta, fare logging, autenticazione, ecc.
  • Si integra facilmente con database come MongoDB, MySQL, ecc., per permettere la gestione dei dati. 
index.js

Da terminale possiamo eseguire il progetto digitando il comando node index, che è il punto di ingresso, corrispondente anche alla chiave “main” nel package.json. Il server sarà in ascolto sulla porta 3000, quindi con il nostro browser oppure postman possiamo effettuare un test dell’ applicazione con:

http://localhost:3000/saluto

http://localhost:3000/lista

index.js

Al progetto abbiamo aggiunto anche la classe Sistema con il metodo getLista() e getSomma(var1,var2) che forniranno i dati alle specifiche richieste, inoltre utilizziamo il file config.js per gestire le varie configurazioni del progetto come la porta 3000 del server ed eventuali configurazioni MySql.

Download progetto: Clienti

—-.-.

ORM – Sequelize

Sequelize è un ORM (Object-Relational Mapping) per Node.js che consente di interagire con database relazionali utilizzando codice JavaScript/TypeScript. Supporta vari database, tra cui MySQL, PostgreSQL, SQLite e MariaDB. Con Sequelize, puoi manipolare i dati in un database MySQL senza dover scrivere direttamente query SQL, semplificando l’accesso e la gestione del database.

Un ORM mappa le tabelle di un database relazionale come oggetti JavaScript.

In altre parole, invece di scrivere query SQL per leggere, scrivere o aggiornare i dati, puoi interagire con il database attraverso metodi e proprietà sugli oggetti JavaScript.

Funzionamento di Sequelize 

Sequelize traduce il codice JavaScript in query SQL che vengono eseguite sul database MySQL. Vediamo i principali aspetti di come Sequelize interagisce con MySQL:

  1. Definizione del Modello: Un modello Sequelize rappresenta una tabella del database. Definendo un modello, si specificano le colonne della tabella come proprietà dell’oggetto JavaScript. Sequelize gestirà quindi la creazione e l’interazione con la tabella MySQL corrispondente.
  2. Connessione al Database: Sequelize richiede l’uso di una stringa di connessione per collegarsi al database MySQL, specificando il nome utente, la password, l’host e il nome del database.
  3. Creazione di Tabelle: Sequelize può creare automaticamente le tabelle nel database in base ai modelli definiti. Questo processo è chiamato “sync”. Utilizzando sequelize.sync(), Sequelize verifica se le tabelle corrispondenti ai modelli esistono nel database, e se non esistono, le crea.
  4. CRUD (Create, Read, Update, Delete): Una volta definiti i modelli, è possibile eseguire operazioni CRUD sul database MySQL attraverso metodi forniti da Sequelize, senza dover scrivere query SQL.
  5. Relazioni tra Tabelle: Sequelize gestisce facilmente le relazioni tra tabelle MySQL, come uno-a-molti, molti-a-molti o uno-a-uno. Queste relazioni vengono definite utilizzando i metodi hasOne, hasMany, belongsTo e belongsToMany.
  6. Transazioni: Sequelize supporta anche transazioni per garantire l’integrità dei dati quando esegui più operazioni che devono essere completate tutte insieme o non essere eseguite affatto.

Per comprendere il funzionamento di Sequelize analizziamo il progetto biblioteca 

/biblioteca-sequelize
|– /config
    |– database.js
|– /models
     |– libro.js
|– /repository
    |– libri_repository.js
|– /routes
    |– libri_routes.js
|– /controllers
     |– libri_controller.js
|– .env
|– index.js
|– package.json

Iniziamo creando una nuova cartella per il nostro progetto Node.js, anche   da  terminale  con i comandi mkdir, cd ed npm init -y. Procediamo con l’ installazione delle dipendenze necessarie per connettersi al database MySQL e lavorare con i moduli ECMAScript:

npm install mysql2  dotenv  express  sequelize

Modificare  il   file   package.json  ed  aggiungere  la   chiave  “type” : “module“ per abilitare i moduli ESM.  

  • mysql2: Questo modulo fornisce un’interfaccia simile a mysql, ma con ottimizzazioni migliori e supporto per le promesse .
    • Le Promise rappresentano un modello di gestione delle operazioni asincrone in JavaScript, introdotto per semplificare la gestione dei flussi asincroni, rendendoli più leggibili e meno soggetti a errori rispetto all’uso dei callback tradizionali.
  • dotenv: Per gestire le variabili di ambiente (in modo da poter gestire le credenziali in sicurezza).

L’ installazione del modulo  dotenv ci consente di utilizzare le variabili d’ ambiente che andremo a definire in un file .env collocato nella root del progetto, ovvero allo stesso livello della punto di ingresso scelto (index.js)

Il modulo mysql2, nel nostro esempio utilizza il file database.js per connettersi a MySQL:

Configurazione MySQL - sequelize

Il file importa il modulo dotenv per recuperare le variabili d’ ambiente dal .env e caricarle nel progetto con la funzione config(). Le variabili verranno tutte caricate in process.env

Di seguito il modello libri.js che deve interagire con la tabella libri di MySQL mappando gli attributi del modello con i campi della tabella, vediamo:

Entità libro

In Sequelize quando definisci un modello con il metodo init(), gli attributi come id, titolo, autore, ecc., rappresentano gli attributi di classe. Nel caso in cui la chiave “field” non è utilizzata il nome dell’ attributo ed il nome campo tabella devono coincidere.

In un progetto Node.js con MySQL (o qualsiasi altro database relazionale) e un ORM come Sequelize, un repository è una classe o un modulo che si occupa dell’interazione diretta con il database per una specifica entità, come ad esempio la tabella libri. Il repository contiene metodi per eseguire operazioni di CRUD (Create, Read, Update, Delete) e altre query complesse, separando la logica di accesso ai dati dal resto dell’applicazione.

Repository Libri

Di seguito un elenco dei metodi predefiniti di Sequelize:

Metodi CRUD di Base
  1. create(data)
  2. findByPk(primaryKey)
  3. findOne(options)
  4. findAll(options)
  5. findAndCountAll(options)
  6. update(values, options)
  7. destroy(options)
  8. bulkCreate(records)
Metodi di Aggregazione
  1. count(options)
  2. sum(field, options)
  3. min(field, options)
  4. max(field, options)
Metodi per Transazioni
  1. transaction()
Metodi per Associazioni
  1. getAssociations()
  2. setAssociations(records)
  3. addAssociation(record)
  4. removeAssociation(record)
Metodi Avanzati
  1. increment(field, options)
  2. decrement(field, options)
  3. reload()
  4. save(options)
Metodi per Gestione della Cache
  1. findOrCreate(options)
  2. upsert(values, options)
Metodi di Query Grezze
  1. sequelize.query(sql, options)
Metodi di Validazione
  1. validate()

Le options in Sequelize ti permettono di configurare e filtrare i risultati delle query o delle operazioni che esegui sul database. Puoi usare queste opzioni per specificare condizioni (where), ordinare i risultati (order), limitare il numero di record (limit), includere associazioni (include), e molto altro.

Ovviamente gli operatori si utilizzano per combinare piu condizioni nella clausola where:

Operatori Logici
Operatori di Confronto
Operatori Stringa
Operatori di Intervallo
Operatori Inclusione/Esclusione
Operatori di Aggregazione e Funzioni
Operatori Speciali

return await Libro.findAll({

     where: {
          autore: {
               [Op.eq]: ‘Umberto Eco’
           }
     }

});

return await Libro.findAll({
        where:{
            titolo:{
                [Op.like]:`%${subTitolo}%` 
            }
        }
 });
return await Libro.findAll({
        where:{
            titolo:{
                [Op.is]: null 
            }
        }
 });
return await Libro.findAll({
        where:{
            pagine:{
                [Op.between]: [100,300]
            }
        }
 });

const libri = await Libro.findAll({    where: {
         [Op.and]: [
               { genere: ‘Fantasy’ }, {
               [Op.or]: [ { autore: ‘J.K. Rowling’ }, { autore: ‘George R.R. Martin’ } ]
               }
        ]
   }
});

const libri = await Libro.findAll({

     where: {

              autore: ‘J.K. Rowling’, 
              genere: ‘Fantasy’, 
              pagine: { [Op.gt]: 300 } 
    },

   attributes: [‘titolo’, ‘pagine’], 
   order: [[‘titolo’, ‘ASC’], [‘pagine’, ‘DESC’]],
});

Sequelize.fn inveceti consente di eseguire funzioni SQL standard in modo dinamico all’interno delle query Sequelize. Queste funzioni coprono diverse categorie, come aggregazione (COUNT, SUM, AVG), manipolazione delle stringhe (UPPER, CONCAT), gestione delle date (NOW, DATE_FORMAT), e altro ancora, rendendo molto flessibile la gestione dei dati nei database tramite Sequelize.

Sequelize.fn(function_name, […arguments])

  • function_name: Il nome della funzione SQL che vuoi invocare, ad esempio 'COUNT', 'SUM', 'UPPER', etc.
  • arguments: Gli argomenti che la funzione SQL accetta. Solitamente si tratta di colonne o valori che vengono passati alla funzione.

Sequelize.fn(‘COUNT’, Sequelize.col(‘id_libro’))

L’ applicazione Biblioteca implementa anche un Controller per gestire la logica applicativa e coordinare i modelli e le viste.

Il controller contiene funzioni che rispondono diverse operazioni CRUD e gestiscono anche le richieste HTTP come GET, DELETE, POST, PUT.

Controller dell' applicazione

Le rotte in un progetto Node.js con Express permettono di definire le operazioni che un’app può eseguire, come creare, leggere, aggiornare o eliminare risorse. Le rotte sono collegate ai controller, che contengono la logica per interagire con il database o altre parti dell’applicazione.

Rotte del progetto

Infine abbiamo il punto di ingresso dell’ applicazione che è il file index.js, come viene specificato anche nel file package.json con la chiave “main”: “index.js”

Punto di Ingresso

Download progetto: Biblioteca

6 commenti

  1. Hi! I know this is kinda off topic but I was wondering if you knew where
    I could locate a captcha plugin for my comment form?
    I’m using the same blog platform as yours and I’m having
    problems finding one? Thanks a lot!

  2. I truly love your blog.. Great colors & theme.

    Did you make this amazing site yourself? Please reply back as I’m attempting to create my very own blog and want to know where you
    got this from or just what the theme is named. Kudos!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *