Il tutorial completo per imparare Node.js da zero: event loop, moduli, NPM, Express, API REST, database, WebSocket, testing, sicurezza e deploy.
Introduzione a Node.js
Node.js è un ambiente di esecuzione (runtime) che permette di eseguire codice JavaScript fuori dal browser, direttamente sul server o sul tuo computer. È costruito sul motore V8 di Google Chrome ed è stato creato da Ryan Dahl nel 2009.
Prima di Node.js, JavaScript viveva solo nel browser. Con Node puoi scrivere server web, API, strumenti da riga di comando, script di automazione e applicazioni real-time, usando un solo linguaggio sia per il frontend che per il backend.
Perché Node.js è così popolare?
⚡ Veloce e non bloccante: gestisce migliaia di connessioni simultanee grazie all'I/O asincrono
🟢 Un solo linguaggio: JavaScript ovunque, frontend e backend
📦 NPM: il più grande ecosistema di librerie open-source al mondo
🏢 Usato da: Netflix, LinkedIn, PayPal, Uber, NASA, Walmart
📘 Node.js non è un linguaggio né un framework: è un runtime. Il linguaggio resta JavaScript. Se non conosci ancora JS, segui prima il corso JavaScript.
Il primo programma Node.js
Get Started — Installazione
Per usare Node.js devi prima installarlo. Scarica la versione LTS (Long Term Support) da nodejs.org: è la più stabile e consigliata per la produzione.
Verifica l'installazione
Dopo l'installazione, apri il terminale e controlla che node e npm siano disponibili.
Verifica e primo script
💡 Usa nvm (Node Version Manager) per installare e cambiare versione di Node senza conflitti: indispensabile quando lavori su più progetti.
Requisiti JavaScript
Node.js è JavaScript, quindi prima di iniziare dovresti conoscere alcune basi del linguaggio. Ecco i concetti fondamentali che userai costantemente.
Concetto
Perché serve in Node
Variabili (let/const)
Dichiarazione e scope del codice
Funzioni e arrow function
Callback, handler, middleware
Oggetti e array
Strutturare dati e risposte JSON
Callback e Promise
Gestione delle operazioni asincrone
async/await
Codice asincrono leggibile
Moduli (import/require)
Organizzare il codice in file
Le basi JS che userai in Node
Node.js vs Browser
Pur usando lo stesso linguaggio, Node.js e il browser sono ambienti molto diversi. Capire le differenze ti evita errori comuni.
Caratteristica
Browser
Node.js
Oggetto globale
window
global / globalThis
DOM
✅ document, window
❌ Non esiste
File system
❌ Limitato
✅ Accesso completo (fs)
Moduli
ES Modules
CommonJS + ES Modules
API di rete
fetch, limitato da CORS
http, https, net (nessun CORS)
📘 In Node non esistono document, window o alert. In compenso hai accesso a file system, processi, rete e variabili d'ambiente.
Node da riga di comando
Node si controlla principalmente dal terminale. Conoscere i comandi e gli argomenti della CLI è essenziale per lo sviluppo quotidiano.
Argomenti e variabili d'ambiente
Comando
Descrizione
node app.js
Esegue un file
node --watch app.js
Riavvia automaticamente a ogni modifica
node -e "console.log(1+1)"
Esegue codice inline
node --inspect app.js
Avvia il debugger
Il motore V8
V8 è il motore JavaScript open-source sviluppato da Google per Chrome. È il cuore di Node.js: compila il codice JavaScript direttamente in codice macchina (JIT — Just-In-Time compilation), rendendolo estremamente veloce.
Cosa fa V8
🔧 Compila JS in codice macchina nativo, non lo interpreta riga per riga
🗑️ Gestisce la garbage collection automatica della memoria
⚡ Ottimizza le funzioni "calde" (eseguite spesso) a runtime
📐 Implementa gli standard ECMAScript più recenti
💡 Node.js = V8 (esegue JS) + libuv (gestisce l'I/O asincrono e l'event loop) + API C++ (file system, rete, crypto). Questa combinazione lo rende potente sul server.
Architettura di Node.js
Node.js usa un'architettura single-threaded (un solo thread principale) con event loop e I/O non bloccante. Questo gli permette di gestire migliaia di connessioni contemporanee senza creare un thread per ognuna.
I componenti principali
V8: esegue il codice JavaScript
libuv: libreria C che fornisce l'event loop e il thread pool per le operazioni di I/O
Event Loop: coordina le callback asincrone
Thread Pool: gestisce in background le operazioni pesanti (file, crypto, DNS)
📘 Anche se il codice JS gira su un solo thread, le operazioni di I/O (lettura file, query database, richieste rete) avvengono in background grazie a libuv. Per questo Node è perfetto per applicazioni I/O-intensive, meno per quelle CPU-intensive.
L'Event Loop
L'Event Loop è il meccanismo che permette a Node, pur essendo single-threaded, di eseguire operazioni non bloccanti. Quando avvii un'operazione asincrona (es. leggere un file), Node la delega a libuv e continua a eseguire il resto del codice; quando l'operazione finisce, la sua callback viene messa in coda ed eseguita.
L'ordine di esecuzione asincrono
⚠️ Le microtask (Promise, queueMicrotask) hanno priorità sulle macrotask (setTimeout, setInterval, I/O). Capire questo ordine evita bug difficili da diagnosticare.
Le fasi dell'event loop
Timers: callback di setTimeout/setInterval
Pending callbacks: callback di sistema rinviate
Poll: recupera nuovi eventi I/O
Check: callback di setImmediate
Close: eventi di chiusura (es. socket.on('close'))
Programmazione asincrona
L'asincronia è il concetto più importante di Node.js. Invece di bloccare il programma in attesa che un'operazione lenta finisca (leggere un file, interrogare un database), Node continua a lavorare e gestisce il risultato quando è pronto, tramite una callback.
Bloccante vs non bloccante
Sincrono (bloccante) vs asincrono
📘 Il pattern error-first callback è lo standard storico di Node: il primo argomento della callback è sempre l'errore (err), il secondo il risultato.
Le Promise
Le Promise rappresentano un valore che sarà disponibile in futuro. Risolvono il problema del "callback hell" (callback annidate illeggibili) permettendo di concatenare operazioni asincrone con .then() e .catch().
Creare e usare una Promise
Async / Await
async/await è la sintassi moderna per gestire le Promise: rende il codice asincrono leggibile come se fosse sincrono. Una funzione async restituisce sempre una Promise, e await ne attende il risultato.
Riscrivere le Promise con async/await
💡 Usa await in sequenza solo quando un'operazione dipende dalla precedente. Per operazioni indipendenti usa Promise.all(): girano in parallelo e sono molto più veloci.
Gestione degli errori
Gestire correttamente gli errori è cruciale in Node: un errore non catturato può crashare l'intero processo. Le strategie cambiano a seconda che il codice sia sincrono, basato su callback o su Promise.
Le tre strategie di error handling
⚠️ Non usare uncaughtException per gestire la logica normale: serve solo a loggare e chiudere il processo in modo pulito. Gestisci sempre gli errori dove si verificano.
I moduli in Node.js
I moduli permettono di dividere il codice in file riutilizzabili. Node usa storicamente il sistema CommonJS: si esporta con module.exports e si importa con require().
Creare e importare un modulo (CommonJS)
📘 Esistono tre tipi di moduli: core (integrati, es. fs), locali (i tuoi file, con ./) e di terze parti (installati con npm, in node_modules).
ES Modules
Gli ES Modules (ESM) sono lo standard ufficiale di JavaScript per i moduli, con import ed export. Node li supporta pienamente: basta usare l'estensione .mjs oppure impostare "type": "module" nel package.json.
Sintassi ES Modules
Caratteristica
CommonJS
ES Modules
Import
require()
import
Export
module.exports
export
Caricamento
Sincrono
Asincrono
Estensione
.js / .cjs
.mjs / "type":"module"
NPM — il gestore di pacchetti
NPM (Node Package Manager) è il gestore di pacchetti di Node e il più grande registro di software open-source al mondo (oltre 2 milioni di pacchetti). Lo usi per installare librerie, gestire dipendenze ed eseguire script.
I comandi NPM essenziali
💡 Alternative a NPM: pnpm (più veloce e con meno spazio su disco) e yarn. Sono compatibili con lo stesso package.json.
Il file package.json
Il package.json è il "documento d'identità" del tuo progetto: contiene nome, versione, dipendenze, script e metadati. È il primo file che npm legge.
Struttura di un package.json
📘 Il simbolo ^ davanti alla versione (es. ^4.19.2) permette aggiornamenti minori e patch ma non major. Il file package-lock.json blocca le versioni esatte per build riproducibili.
Gli script NPM
Gli script NPM, definiti nella sezione "scripts" del package.json, automatizzano i comandi ricorrenti: avviare il server, eseguire i test, fare il build. Si lanciano con npm run nome.
Definire ed eseguire script
💡 Puoi concatenare script con && (in sequenza) e usare gli hook pre e post: ad esempio pretest gira automaticamente prima di test.
Gestire le dipendenze
Mantenere le dipendenze aggiornate e sicure è parte essenziale della manutenzione di un progetto. NPM offre strumenti per controllare versioni obsolete e vulnerabilità.
Controllo e sicurezza delle dipendenze
Tipo
Quando si usa
dependencies
Necessarie in produzione (express, mongoose...)
devDependencies
Solo in sviluppo (nodemon, eslint, jest...)
peerDependencies
Richieste dall'host (tipico nei plugin)
Pubblicare pacchetti su NPM
Puoi pubblicare le tue librerie sul registro pubblico di NPM perché chiunque possa installarle. Serve un account gratuito su npmjs.com.
Pubblicare un pacchetto
⚠️ Una versione pubblicata non può essere sovrascritta: per modifiche devi sempre incrementare il numero di versione seguendo il semantic versioning (major.minor.patch).
Modulo HTTP
Il modulo http permette di creare server web e gestire richieste/risposte senza alcuna libreria esterna. È la base su cui sono costruiti framework come Express.
Un server HTTP minimale
📘 L'oggetto req contiene i dati della richiesta (url, method, headers), res serve a costruire la risposta. Tutto è basato su stream.
Modulo HTTPS
Il modulo https è la versione sicura di http: cifra la comunicazione con TLS/SSL. In produzione di solito il TLS è gestito da un reverse proxy (Nginx) o dalla piattaforma di hosting, ma è utile saperlo configurare.
Server HTTPS con certificato
File System (fs)
Il modulo fs permette di leggere, scrivere, modificare ed eliminare file e cartelle. Offre versioni sincrone, con callback e basate su Promise.
Operazioni sui file
💡 Per file di grandi dimensioni usa gli stream invece di readFile: leggono il file a pezzi senza caricarlo tutto in memoria.
Modulo Path
Il modulo path gestisce i percorsi di file e cartelle in modo indipendente dal sistema operativo (Windows usa \, Linux/Mac usano /).
Manipolare i percorsi
📘 Usa SEMPRE path.join() per costruire percorsi: concatenare stringhe con / manualmente crea bug su Windows.
Modulo OS
Il modulo os fornisce informazioni sul sistema operativo e sull'hardware su cui gira Node: CPU, memoria, rete, utente.
Informazioni di sistema
Modulo URL
Il modulo url (e la classe globale URL) serve ad analizzare e costruire indirizzi web, estraendo host, percorso, parametri della query.
Analizzare un URL
Modulo Events
Il modulo events implementa il pattern publish/subscribe tramite la classe EventEmitter. Gran parte di Node (stream, server HTTP, processi) è costruita su di esso.
Emettere e ascoltare eventi
Modulo Stream
Gli stream permettono di elaborare dati a pezzi (chunk) invece di caricarli tutti in memoria. Sono ideali per file grandi, video, upload e qualsiasi flusso di dati continuo.
Copiare un file con gli stream
Tipo di stream
Esempio
Readable
fs.createReadStream, req
Writable
fs.createWriteStream, res
Duplex
socket TCP
Transform
zlib.createGzip (comprime al volo)
Modulo Buffer
Un Buffer è un'area di memoria che contiene dati binari grezzi. Serve quando si lavora con file, immagini, protocolli di rete o dati non testuali, prima che JavaScript supportasse nativamente i binari.
Lavorare con i Buffer
Modulo Crypto
Il modulo crypto fornisce funzioni crittografiche: hashing, cifratura, firme digitali e generazione di valori casuali sicuri. Fondamentale per la sicurezza (password, token, integrità dei dati).
Hashing e valori casuali
⚠️ Non salvare mai le password con un semplice hash SHA-256. Usa algoritmi lenti progettati per le password come bcrypt, scrypt o argon2, sempre con un salt.
Modulo Timers
I timer permettono di eseguire codice dopo un ritardo o a intervalli regolari. Sono globali (non serve require) e sono gestiti dall'event loop.
setTimeout, setInterval, setImmediate
Modulo DNS
Il modulo dns risolve i nomi di dominio in indirizzi IP e viceversa, interrogando i server DNS. Utile per diagnostica di rete e validazione.
Risoluzione DNS
Modulo Assert
Il modulo assert fornisce funzioni per verificare che le condizioni siano vere. Se un'asserzione fallisce, lancia un errore. È la base dei test e dei controlli di invarianti nel codice.
Asserzioni
📘 assert è perfetto per i test integrati con il test runner nativo di Node (node --test), senza installare librerie esterne.
Modulo Util
Il modulo util raccoglie funzioni di utilità per il debugging, la formattazione e la conversione tra stili di codice asincrono.
Utility più usate
Modulo Readline
Il modulo readline legge l'input dell'utente dal terminale riga per riga. È la base per creare interfacce a riga di comando interattive.
Input interattivo da terminale
Node ES6+ e funzionalità moderne
Node.js supporta tutte le funzionalità moderne di JavaScript (ES6 e successive) grazie all'aggiornamento costante del motore V8. Ecco quelle che userai di più nel codice server.
Funzionalità ES moderne in Node
L'oggetto Process
L'oggetto globale process fornisce informazioni e controllo sul processo Node corrente: argomenti, variabili d'ambiente, input/output standard, segnali ed eventi del ciclo di vita.
Usare process
💡 Gestire i segnali SIGINT e SIGTERM permette un "graceful shutdown": chiudere connessioni al database e richieste in corso prima di terminare.
Node con TypeScript
Usare TypeScript con Node aggiunge la tipizzazione statica al backend: meno bug, autocompletamento migliore e refactoring sicuro. Dalle versioni recenti, Node può eseguire TypeScript anche direttamente.
Setup di Node + TypeScript
📘 Approfondisci con il nostro corso TypeScript completo: tipi, generics, interfacce e decorators applicabili anche al backend Node.
Node con TypeScript avanzato
In progetti backend reali, TypeScript brilla nel tipizzare richieste, risposte, modelli di dati e configurazioni. Ecco i pattern più utili con Node ed Express.
Tipizzare Express e i dati
💡 Strumenti come tsx e ts-node eseguono TypeScript senza compilazione manuale durante lo sviluppo, con riavvio automatico.
Lint e formattazione
ESLint analizza il codice per trovare errori e applicare convenzioni; Prettier formatta automaticamente per uno stile coerente. Insieme tengono il codice pulito e uniforme in tutto il team.
Configurare ESLint e Prettier
💡 Integra ESLint e Prettier nel tuo editor (VS Code) e in un hook pre-commit con husky: il codice viene controllato e formattato automaticamente a ogni commit.
I framework Node.js
Costruire un'app solo con il modulo http è possibile ma laborioso. I framework aggiungono routing, middleware, gestione degli errori e molto altro, accelerando lo sviluppo.
Framework
Caratteristiche
Express
Il più diffuso, minimale e flessibile
Fastify
Velocissimo, con validazione integrata
NestJS
Strutturato, TypeScript-first, stile Angular
Koa
Moderno, async/await, creato dal team di Express
Hapi
Configurazione-centrico, robusto per enterprise
📘 Per imparare i concetti, Express è il punto di partenza ideale: la maggior parte dei tutorial e delle offerte di lavoro lo richiedono.
Express.js
Express è il framework web più popolare per Node. Semplifica la creazione di server, la definizione delle rotte e la gestione di richieste e risposte.
Un'app Express completa
💡 Installa Express con npm install express. I parametri dinamici (:id) si leggono da req.params, la query string da req.query, il body da req.body.
Il concetto di Middleware
Un middleware è una funzione che si inserisce nel ciclo richiesta-risposta. Riceve req, res e next, può modificare la richiesta, terminarla o passarla al middleware successivo chiamando next().
Middleware in Express
📘 L'ordine dei middleware conta: vengono eseguiti nell'ordine in cui sono dichiarati. Il middleware di gestione errori va sempre per ultimo e ha 4 argomenti.
Progettare API REST
Un'API REST espone risorse tramite URL e usa i metodi HTTP per le operazioni CRUD (Create, Read, Update, Delete). È lo standard per la comunicazione tra client e server.
CRUD REST con Express
Metodo
Azione
Codice di successo
GET
Leggere
200 OK
POST
Creare
201 Created
PUT/PATCH
Aggiornare
200 OK
DELETE
Eliminare
204 No Content
Autenticazione delle API
Proteggere le API significa verificare l'identità di chi le chiama. Il metodo più diffuso nelle API REST è il JWT (JSON Web Token): il server emette un token firmato che il client invia a ogni richiesta.
Autenticazione con JWT
⚠️ Conserva il segreto JWT in una variabile d'ambiente, mai nel codice. Usa sempre HTTPS e scadenze brevi per i token. Per le password usa bcrypt.
Node.js con il Frontend
Node può servire file statici (HTML, CSS, JS) e fornire le API che il frontend consuma. È il cuore dello stack moderno: backend Node + frontend React/Vue/Angular.
Servire file statici e API
💡 In sviluppo, frontend e backend girano spesso su porte diverse: configura CORS (pacchetto cors) o un proxy per farli comunicare.
MySQL — Iniziare
Node si connette a MySQL tramite il pacchetto mysql2. Permette di eseguire query SQL e gestire i risultati in modo asincrono.
Connessione a MySQL
📘 Installa con npm install mysql2. La versione mysql2/promise supporta async/await. Per le basi SQL consulta i nostri corso MySQL e corso SQL.
MySQL — Creare un database
Puoi creare database e gestirli direttamente da Node eseguendo i comandi SQL appropriati.
Creare un database
MySQL — Creare una tabella
Le tabelle definiscono la struttura dei dati. Si creano con CREATE TABLE specificando colonne e tipi.
Creare una tabella
MySQL — Insert Into
Per inserire dati usa INSERT INTO. Usa sempre i placeholder? per prevenire SQL injection.
Inserire dati in sicurezza
⚠️ Non concatenare MAI i valori nelle query (es. "... VALUES ('" + nome + "')"): è la causa principale di SQL injection. Usa sempre i placeholder.
MySQL — Select From
SELECT recupera i dati. I risultati arrivano come array di oggetti.
Selezionare dati
MySQL — Where
La clausola WHERE filtra le righe in base a condizioni.
Filtrare con WHERE
MySQL — Order By
ORDER BY ordina i risultati per una o più colonne, in ordine crescente (ASC) o decrescente (DESC).
Ordinare i risultati
MySQL — Delete
DELETE rimuove righe. Usa sempre una clausola WHERE, altrimenti cancelli l'intera tabella.
Eliminare righe
⚠️ DELETE FROM clienti senza WHERE cancella TUTTE le righe. Controlla sempre due volte prima di eseguire una DELETE.
MySQL — Drop Table
DROP TABLE elimina completamente una tabella, struttura e dati. Operazione irreversibile.
Eliminare una tabella
MySQL — Update
UPDATE modifica righe esistenti. Anche qui WHERE è essenziale per non aggiornare tutto.
Aggiornare righe
MySQL — Limit
LIMIT restringe il numero di righe restituite. Con OFFSET realizza la paginazione.
Limitare e paginare
MySQL — Join
Le JOIN combinano righe da più tabelle in base a una relazione, di solito una chiave esterna.
MongoDB è un database NoSQL che memorizza i dati come documenti JSON-like (BSON), senza schema fisso. Node vi si connette con il driver ufficiale mongodb o con l'ODM Mongoose.
Connessione a MongoDB
📘 Installa con npm install mongodb. In alternativa Mongoose (npm install mongoose) aggiunge schemi e validazione. MongoDB Atlas offre un database cloud gratuito.
MongoDB — Creare un database
In MongoDB database e collezioni vengono creati automaticamente al primo inserimento di dati: non serve definirli in anticipo.
Selezionare database e collezione
MongoDB — Collezioni
Una collezione è l'equivalente di una tabella: un gruppo di documenti. I documenti nella stessa collezione non devono avere la stessa struttura.
Gestire le collezioni
MongoDB — Insert
Si inseriscono documenti con insertOne (singolo) o insertMany (multipli). MongoDB genera automaticamente un campo _id univoco.
Inserire documenti
MongoDB — Find
find recupera più documenti, findOne uno solo. Senza filtro restituiscono tutto.
Trovare documenti
MongoDB — Query
MongoDB usa operatori speciali per le query: $gt, $lt, $in, $and, $or e altri.
Query con operatori
MongoDB — Sort
sort ordina i risultati: 1 per crescente, -1 per decrescente.
Ordinare i documenti
MongoDB — Delete
deleteOne elimina il primo documento che corrisponde, deleteMany tutti quelli che corrispondono.
Eliminare documenti
⚠️ deleteMany({}) con filtro vuoto elimina TUTTI i documenti della collezione. Verifica sempre il filtro.
MongoDB — Drop Collection
drop elimina un'intera collezione con tutti i suoi documenti.
Eliminare una collezione
MongoDB — Update
Si aggiorna con updateOne / updateMany usando operatori come $set (imposta valori) e $inc (incrementa).
Aggiornare documenti
MongoDB — Limit
limit restringe il numero di documenti; con skip si realizza la paginazione.
Limitare e paginare
MongoDB — Join ($lookup)
MongoDB realizza le "join" tramite l'operatore $lookup nella pipeline di aggregazione, combinando documenti di collezioni diverse.
Join con $lookup
💡 In MongoDB spesso si preferisce incorporare i dati correlati in un unico documento invece di usare $lookup: è più veloce in lettura.
GraphQL con Node
GraphQL è un'alternativa alle API REST: il client specifica esattamente quali dati vuole in un'unica richiesta, evitando over-fetching e under-fetching. Con Node si usa con graphql o server come Apollo.
Server GraphQL minimale
Socket.IO
Socket.IO abilita la comunicazione bidirezionale in tempo reale tra server e client, ideale per chat, notifiche e dashboard live. Gestisce automaticamente i fallback se i WebSocket non sono disponibili.
Chat in tempo reale
WebSockets
I WebSocket sono il protocollo standard per una connessione persistente e bidirezionale tra browser e server. Socket.IO li usa sotto il cofano, ma puoi usarli direttamente con il pacchetto ws.
Server WebSocket con ws
📘 Differenza: WebSocket è il protocollo grezzo; Socket.IO è una libreria che ci aggiunge stanze, riconnessione automatica e fallback. Scegli ws per il controllo, Socket.IO per la comodità.
Debugging avanzato
Oltre ai console.log, Node offre un debugger completo integrato, utilizzabile da terminale o tramite Chrome DevTools e VS Code.
Debugging con --inspect
💡 In VS Code crea un file .vscode/launch.json per debuggare con breakpoint grafici, ispezione delle variabili e call stack.
Testare le applicazioni
I test automatici verificano che il codice funzioni e continui a funzionare dopo le modifiche. Node ha un test runner integrato (node --test) da Node 18+.
Test con il runner nativo
Framework di test
Oltre al runner nativo, esistono framework di test maturi con più funzionalità: mock, coverage, snapshot.
Framework
Caratteristiche
Jest
Tutto-in-uno, mock e coverage integrati, molto diffuso
Vitest
Velocissimo, compatibile con Jest, ideale con Vite/TS
Mocha + Chai
Flessibile e configurabile, storico
Supertest
Per testare le API HTTP/Express
Test di un'API con Jest e Supertest
Il Test Runner di Node
Il test runner integrato di Node è stabile da Node 20 e non richiede dipendenze. Supporta suite, hook, mock e report di coverage.
Funzionalità del runner nativo
Variabili d'ambiente
Le variabili d'ambiente separano la configurazione dal codice: credenziali, chiavi API e URL del database non vanno mai scritti nel codice sorgente.
Gestire la configurazione
⚠️ Aggiungi sempre .env al .gitignore: non deve MAI finire nel repository. Fornisci invece un .env.example con le chiavi ma senza valori reali.
Sviluppo vs Produzione
L'ambiente di sviluppo privilegia velocità di iterazione e debug; quello di produzione privilegia stabilità, sicurezza e performance. La variabile NODE_ENV distingue i due.
Comportamento per ambiente
Aspetto
Sviluppo
Produzione
Errori
Stack completo
Messaggi generici
Riavvio
nodemon / --watch
PM2 / cluster
Log
Verbosi e colorati
Strutturati (JSON)
Cache
Disabilitata
Aggressiva
CI/CD
CI/CD (Continuous Integration / Continuous Deployment) automatizza test e rilascio: a ogni push, una pipeline esegue lint, test e deploy. GitHub Actions è la soluzione più immediata.
Pipeline GitHub Actions
💡 npm ci (invece di npm install) installa esattamente le versioni del package-lock.json: più veloce e riproducibile, ideale nelle pipeline.
Sicurezza in Node.js
La sicurezza è una responsabilità costante. Ecco le pratiche essenziali per proteggere un'applicazione Node in produzione.
🔒 Usa HTTPS ovunque
🛡️ Aggiungi helmet per gli header di sicurezza HTTP
🚦 Limita le richieste con rate limiting (anti brute-force)
🧹 Valida e sanifica ogni input (es. con Zod o Joi)
🔑 Hash delle password con bcrypt, mai in chiaro
📦 Esegui npm audit regolarmente
Hardening di base con Express
📘 Per i fondamenti di sicurezza informatica vedi il nostro corso Cybersecurity.
Deploy di un'app Node
Mettere online un'app Node significa eseguirla su un server raggiungibile da Internet. Le opzioni vanno dai PaaS più semplici ai container.
Piattaforma
Ideale per
Render / Railway
Deploy rapido, ottimi per iniziare
Vercel / Netlify
API serverless e frontend
Fly.io
Container vicini agli utenti
AWS / DigitalOcean
Controllo completo, VPS
Docker
Ambiente riproducibile ovunque
Dockerfile e PM2
Logging
Un buon logging è fondamentale per capire cosa succede in produzione. I log strutturati (JSON) sono facili da cercare e analizzare con strumenti come Grafana o Datadog.
Logging strutturato con Pino
💡 Evita console.log in produzione: è sincrono e lento. Librerie come Pino e Winston sono asincrone e strutturate.
Monitoraggio
Il monitoraggio osserva la salute dell'app in tempo reale: tempi di risposta, uso di CPU/memoria, tassi di errore. Permette di reagire ai problemi prima degli utenti.
Health check ed esposizione metriche
Ottimizzare le performance
Node è veloce, ma alcune pratiche fanno la differenza sotto carico. L'obiettivo è non bloccare mai l'event loop e ridurre il lavoro inutile.
⚡ Non bloccare l'event loop con operazioni CPU pesanti (usa worker threads)
🗄️ Usa una cache (Redis) per dati richiesti spesso
📦 Abilita la compressione gzip delle risposte
🔁 Usa connection pooling per i database
📊 Profila con --prof e il modulo perf_hooks
Compressione e cache
Modulo Child Process
Il modulo child_process permette di eseguire altri programmi o comandi di sistema da Node, creando processi figli separati.
Eseguire processi esterni
📘 Usa spawn per processi con molto output o lunghi (usa stream), exec per comandi rapidi. fork è specializzato per creare altri processi Node che comunicano via messaggi.
Modulo Cluster
Node usa un solo core per default. Il modulo cluster crea più processi worker (uno per core CPU) che condividono la stessa porta, moltiplicando la capacità di gestire richieste.
Sfruttare tutti i core
💡 In produzione, PM2 in modalità cluster (pm2 start app.js -i max) fa la stessa cosa con riavvio automatico e zero-downtime reload.
Worker Threads
I worker threads eseguono codice JavaScript in thread paralleli reali, condividendo memoria. Sono la soluzione per le operazioni CPU-intensive (calcoli pesanti, elaborazione immagini) senza bloccare l'event loop principale.
Calcolo pesante in un thread separato
📘 Cluster scala le richieste di rete (più processi); Worker threads scalano il calcolo CPU (più thread nello stesso processo, con memoria condivisa).
Microservizi
L'architettura a microservizi divide un'applicazione in servizi piccoli e indipendenti, ognuno con una responsabilità precisa, che comunicano via rete (HTTP, gRPC o code di messaggi). Node è popolare per i microservizi grazie alla leggerezza e all'avvio rapido.
Vantaggi e sfide
✅ Scalabilità indipendente di ogni servizio
✅ Deploy e tecnologie indipendenti per team diversi
⚠️ Maggiore complessità operativa (rete, osservabilità)
⚠️ Gestione della consistenza dei dati distribuiti
💡 Strumenti tipici: RabbitMQ/Kafka per la messaggistica, Docker+Kubernetes per l'orchestrazione, un API Gateway come punto d'ingresso unico.
WebAssembly in Node
WebAssembly (Wasm) permette di eseguire in Node codice compilato da linguaggi come C, C++ o Rust, a velocità quasi nativa. Utile per algoritmi critici per le prestazioni.
Eseguire un modulo Wasm
📘 Wasm è ideale per compiti CPU-intensive (crittografia, compressione, elaborazione media) dove JavaScript puro sarebbe troppo lento.
Modulo HTTP/2
Il modulo http2 implementa il protocollo HTTP/2, che migliora le performance con multiplexing (più richieste su una connessione), compressione degli header e server push.
Server HTTP/2
Modulo Perf Hooks
Il modulo perf_hooks fornisce strumenti di misurazione delle prestazioni ad alta precisione, basati sulla Performance Timing API del browser.
Misurare i tempi di esecuzione
Modulo VM
Il modulo vm esegue codice JavaScript in un contesto isolato (sandbox). Utile per eseguire codice dinamico, ma da usare con grande cautela per motivi di sicurezza.
Eseguire codice in una sandbox
⚠️ Il modulo vm NON è una sandbox di sicurezza completa: codice malevolo può comunque uscirne. Per eseguire codice non fidato usa soluzioni isolate come isolated-vm o container separati.
Modulo TLS/SSL
Il modulo tls implementa i protocolli TLS/SSL per comunicazioni cifrate e autenticate. È la base di https e di qualsiasi connessione sicura.
Server TLS
Modulo Net
Il modulo net fornisce API per creare server e client TCP, alla base di molti protocolli di rete. Lavora a un livello più basso di http.
Server e client TCP
Modulo Zlib
Il modulo zlib fornisce compressione e decompressione (Gzip, Deflate, Brotli). Riduce la dimensione di file e risposte HTTP, risparmiando banda.
Comprimere dati e file
Esempi del mondo reale
Mettendo insieme tutto ciò che hai imparato, ecco i tipi di applicazioni che puoi costruire con Node.js nel mondo reale.
💬 App di chat: Socket.IO + Redis per il pub/sub tra istanze
📊 Dashboard real-time: WebSocket + stream di dati
🤖 Bot e automazioni: API di terze parti + cron job
📁 Servizi di upload: stream + storage cloud (S3)
🔗 API Gateway / BFF: aggregare più microservizi
⚙️ Tool da riga di comando: automazione dello sviluppo
🎯 Progetto consigliato
Costruisci un'API REST completa per un blog: autenticazione JWT, CRUD degli articoli su MongoDB, validazione degli input, rate limiting, test automatici e deploy su Render. È il progetto perfetto per il tuo portfolio.
Raspberry Pi con Node.js
Node.js gira benissimo sul Raspberry Pi, il mini-computer perfetto per progetti IoT. Puoi controllare LED, sensori e motori direttamente da JavaScript.
Setup su Raspberry Pi
📘 Il Raspberry Pi ha pin GPIO (General Purpose Input/Output) che permettono di interagire con il mondo fisico: accendere luci, leggere sensori, azionare relè.
Introduzione al GPIO
I pin GPIO sono l'interfaccia tra il Raspberry Pi e i componenti elettronici. Ogni pin può essere configurato come output (per controllare) o input (per leggere).
Controllare un pin GPIO
LED lampeggiante
Il classico "Hello World" dell'elettronica: far lampeggiare un LED. Combina GPIO e timer.
LED che lampeggia
LED e pulsante
Leggere un input (pulsante) e reagire controllando un output (LED): la base dell'interazione fisica.
Accendere un LED con un pulsante
LED in sequenza
Controllare più LED in sequenza per creare un effetto "luce che scorre", gestendo un array di pin.
Effetto luci scorrevoli
RasPi e WebSocket
Combinando GPIO e WebSocket puoi controllare l'hardware da remoto, in tempo reale, da una pagina web o un'app.
Controllo remoto di un LED
LED RGB via WebSocket
Un LED RGB combina tre colori (rosso, verde, blu). Con il PWM puoi regolarne l'intensità e creare qualsiasi colore, controllabile da remoto.
Controllo colore RGB
Componenti elettronici
Per i progetti IoT con Raspberry Pi e Node.js ti serviranno alcuni componenti di base. Ecco i più comuni e a cosa servono.
Componente
Uso
LED
Segnalazione luminosa
Resistore
Limitare la corrente (protegge i LED)
Pulsante
Input dall'utente
Breadboard
Prototipazione senza saldature
Sensore DHT22
Temperatura e umidità
Sensore PIR
Rilevamento del movimento
Servomotore
Movimento controllato
Relè
Controllare dispositivi a 220V
💡 Inizia con un kit starter per Raspberry Pi: contiene breadboard, LED, resistori, pulsanti e cavi jumper, tutto ciò che serve per i primi progetti.
Editor Node.js online
Ogni esempio di questo corso ha il pulsante ▶ Provalo tu: si apre un editor dove puoi leggere e modificare il codice con la sintassi colorata. Poiché Node gira sul server, per eseguirlo usa uno degli ambienti qui sotto.
Dove eseguire Node.js online
🟢 StackBlitz — ambiente Node.js completo nel browser, avvio istantaneo
🔵 Replit — esegui Node senza installare nulla, ottimo per imparare
💻 Locale — installa Node da nodejs.org e lancia node file.js
Prova questo nel tuo editor
Esercizi Node.js
Il modo migliore per imparare Node è scrivere codice. Ecco una serie di esercizi progressivi: prova a risolverli prima di guardare una soluzione.
Livello base
Scrivi uno script che legge un file di testo e conta quante righe contiene
Crea un server HTTP che risponde "Ciao" su / e l'ora corrente su /ora
Scrivi un modulo calcolatrice.js con somma, sottrazione, moltiplicazione e dividi, ed importalo
Livello intermedio
Crea un'API REST con Express per una lista di "task" (CRUD completo in memoria)
Leggi un file JSON di prodotti, filtra quelli sotto i 20€ e salva il risultato in un nuovo file
Crea uno script CLI che chiede nome ed età all'utente e li salva in un file
Livello avanzato
Aggiungi autenticazione JWT all'API dei task del punto precedente
Collega l'API a un database MongoDB con Mongoose
Crea una chat in tempo reale con Socket.IO
🎯 Sfida
Costruisci un accorciatore di URL: un'API che riceve un URL lungo, genera un codice breve, lo salva e reindirizza dal codice all'URL originale. Usa Express + un database.
Quiz Node.js
Metti alla prova le tue conoscenze con queste domande. Le risposte sono in fondo.
Su quale motore JavaScript è costruito Node.js?
Qual è la differenza tra fs.readFile e fs.readFileSync?
Cosa fa l'event loop?
Qual è la differenza tra dependencies e devDependencies?
Cosa restituisce sempre una funzione async?
Quale modulo si usa per creare un server web senza librerie esterne?
A cosa serve module.exports?
Qual è la differenza tra cluster e worker_threads?
Perché non si devono concatenare i valori nelle query SQL?
Cosa serve nel .gitignore per proteggere le credenziali?
📘 Risposte: 1) V8. 2) readFile è asincrono (non bloccante), readFileSync è sincrono (bloccante). 3) Coordina l'esecuzione delle callback asincrone su un thread singolo. 4) dependencies servono in produzione, devDependencies solo in sviluppo. 5) Una Promise. 6) Il modulo http. 7) Esportare valori/funzioni da un modulo CommonJS. 8) cluster usa più processi (scala le richieste), worker_threads usa thread (scala la CPU). 9) Per prevenire SQL injection. 10) Il file .env.
Problemi pratici
Progetti completi da realizzare per consolidare le competenze e arricchire il portfolio. Ognuno copre più argomenti del corso.
Progetto
Tecnologie
API REST per blog
Express + MongoDB + JWT
Chat real-time
Socket.IO + Express
Accorciatore URL
Express + MySQL
Scraper di dati con CLI
fetch + fs + child_process
Dashboard di monitoraggio
WebSocket + perf_hooks
Bot Telegram/Discord
API esterne + webhook
Sistema di upload file
Multer + stream + storage
💡 Pubblica ogni progetto su GitHub con un README chiaro: è ciò che i recruiter guardano per primo. Un portfolio di 3-4 progetti Node ben fatti vale più di mille certificati.
Programma del corso
Questo corso copre l'intero percorso Node.js, dai fondamenti agli argomenti avanzati. Ecco la mappa completa di ciò che hai a disposizione.
Un percorso suggerito per imparare Node.js in modo strutturato. Adatta i tempi al tuo ritmo, ma rispetta l'ordine: ogni fase costruisce sulla precedente.
Deploy, CI/CD, performance + progetto finale di portfolio
📘 Prerequisito: una buona conoscenza di JavaScript. Se ti serve, ripassa con il corso JavaScript prima di iniziare.
Domande da colloquio
Le domande più frequenti nei colloqui per sviluppatore Node.js. Preparale bene: dimostrano la comprensione dei concetti, non solo la sintassi.
🔹 Spiega l'event loop e la differenza tra microtask e macrotask
🔹 Perché Node è single-threaded ma può gestire molte connessioni?
🔹 Differenza tra process.nextTick, setImmediate e setTimeout
🔹 Come gestisci gli errori in codice asincrono?
🔹 Cos'è il middleware in Express e come funziona la catena?
🔹 Come scaleresti un'app Node sotto carico elevato?
🔹 Differenza tra cluster e worker threads
🔹 Come proteggi un'API REST?
🔹 Cosa sono gli stream e quando li useresti?
🔹 Differenza tra SQL e NoSQL, quando scegliere quale?
💡 Accompagna ogni risposta teorica con un esempio concreto da un tuo progetto: i selezionatori valutano l'esperienza pratica più della definizione a memoria.
Bootcamp Node.js
Un percorso intensivo per diventare sviluppatore backend Node.js in poche settimane, combinando teoria e tanta pratica.
Cosa imparerai
✅ JavaScript moderno applicato al backend
✅ Architettura di API REST professionali
✅ Database relazionali e NoSQL
✅ Autenticazione, sicurezza e testing
✅ Deploy in produzione e CI/CD
✅ Un progetto reale completo per il portfolio
📘 Vuoi un percorso guidato con un docente? Prenota una lezione o scrivi tramite il modulo contatti: costruiamo insieme un piano su misura.
Certificazione Node.js
Una certificazione attesta le tue competenze Node.js e arricchisce il CV. Ecco le opzioni più riconosciute, dalle ufficiali alle pratiche.
Certificazione
Ente
Note
OpenJS Node.js Application Developer (JSNAD)
OpenJS Foundation
La più autorevole, ufficiale
OpenJS Node.js Services Developer (JSNSD)
OpenJS Foundation
Focus su sicurezza e API
Node.js Certificate
W3Schools
Base, buona per iniziare
Back End Development and APIs
freeCodeCamp
Gratuita, molto pratica
Progetti su GitHub
Portfolio
La prova pratica più convincente
Come prepararsi
📚 Padroneggia event loop, stream, moduli core ed errori asincroni
🏗️ Costruisci almeno 2-3 API REST complete con database e autenticazione
🧪 Sai scrivere test e fare debugging
🚀 Hai fatto almeno un deploy reale in produzione
Conclusione — E ora?
Hai completato il corso Node.js! Hai imparato l'event loop e l'asincronia, i moduli e NPM, tutti i moduli core, Express e le API REST, l'autenticazione, i database MySQL e MongoDB, WebSocket e GraphQL, testing, sicurezza, deploy, performance e persino l'IoT con Raspberry Pi.
I tuoi prossimi passi
🏗️ Costruisci un progetto reale end-to-end e mettilo online: è ciò che consolida davvero le competenze
⚛️ Collega un frontend con il corso React per diventare full-stack
🚀 Esplora NestJS o Fastify per architetture più strutturate
🗄️ Approfondisci i database con i corsi MySQL e SQL
🐳 Impara Docker e Kubernetes per il deploy professionale
🎯 La tua sfida finale
Costruisci e pubblica un'API REST full-stack completa: autenticazione JWT, database, validazione, test automatici, documentazione e deploy in produzione. Aggiungi un frontend che la consuma. Questo singolo progetto dimostra tutte le competenze di uno sviluppatore backend Node.js junior.