Introduzione
Node.js è un ambiente di esecuzione JavaScript che permette di eseguire codice JavaScript al di fuori del browser. Utilizza il motore V8 di Chrome arricchito con API specifiche per operazioni lato server come accesso al file system, creazione di server HTTP e comunicazione con database.
In questo capitolo si approfondiscono:
- Node.js vs Browser: differenze tra gli ambienti
- Moduli Node.js: sintassi
requireemodule.exports - File System: leggere e scrivere file
- Server HTTP: creare server con il modulo
http - Express.js: framework per applicazioni web
- REST API: creare endpoint per scambiare dati JSON
- Database MongoDB: integrazione base con MongoDB
Node.js vs Browser
Cos’è Node.js
Node.js è essenzialmente il motore JavaScript V8 di Chrome estratto dal browser e arricchito con API specifiche per l’ambiente server. Questo permette di eseguire JavaScript al di fuori del browser, aprendo possibilità completamente nuove rispetto al tradizionale JavaScript lato client.
Differenze Principali
Browser:
- API disponibili: DOM per manipolare HTML,
fetchper richieste HTTP,localStorageper storage locale,windowcome oggetto globale - Esecuzione: il codice viene eseguito nel browser dell’utente, direttamente sulla macchina del visitatore
- Scopo principale: creare interfacce utente interattive e reattive
Node.js:
- API disponibili: file system per leggere/scrivere file, modulo
httpper creare server, moduli core per operazioni di sistema - Esecuzione: il codice viene eseguito su un server o sulla macchina locale dello sviluppatore
- Scopo principale: creare server web, script utility, tooling per sviluppo, applicazioni backend
Cosa Rimane Uguale
La sintassi JavaScript base è completamente identica tra browser e Node.js:
- Dichiarazione di variabili (
const,let,var) - Definizione di funzioni, classi, oggetti
- Metodi degli array (
map,filter,reduce, ecc.) - Gestione asincrona (
async/await, Promises) - Tutte le funzionalità core del linguaggio JavaScript
Questo significa che tutto ciò che si è imparato sul linguaggio JavaScript stesso è applicabile anche in Node.js. La differenza sta solo nelle API disponibili e nell’ambiente di esecuzione.
Eseguire Script Node.js
Per eseguire un file JavaScript con Node.js, si usa il comando node seguito dal nome del file:
node app.jsNode.js legge il file JavaScript specificato, lo esegue e termina quando il codice è completato. Se il codice avvia un server o un processo continuo, Node.js rimane in esecuzione finché il processo non viene terminato manualmente.
Moduli Node.js
Sistema di Moduli
Node.js utilizza un sistema di moduli basato su CommonJS, diverso dai moduli ES6 utilizzati nel browser. Questo sistema permette di organizzare il codice in file separati e riutilizzabili, importando funzionalità quando necessario.
Sintassi Import/Export
Importare un modulo:
Node.js usa require() per importare moduli. Il comportamento varia in base al tipo di modulo:
const fs = require('fs'); // Modulo core (built-in)const express = require('express'); // Pacchetto npm installatoconst myModule = require('./myModule'); // File locale (percorso relativo)Quando si importa un modulo core o un pacchetto npm, si specifica solo il nome. Per file locali, bisogna usare un percorso relativo che inizi con ./ o ../.
Esportare da un modulo:
Per rendere disponibili funzioni, oggetti o valori ad altri file, si usa module.exports:
// Esportare un singolo valore (funzione, oggetto, ecc.)module.exports = myFunction;
// Esportare un oggetto con più proprietàmodule.exports = { function1: myFunction1, function2: myFunction2};
// Esportare multipli valori aggiungendo proprietàmodule.exports.function1 = myFunction1;module.exports.function2 = myFunction2;La differenza principale con i moduli ES6 è che module.exports può essere assegnato direttamente, mentre con ES6 si usa export prima della dichiarazione.
Moduli Core
Node.js include molti moduli built-in disponibili senza installazione. Questi moduli forniscono funzionalità fondamentali per operazioni comuni:
fs: operazioni sul file system (leggere, scrivere, gestire file e cartelle)http: creare server HTTP e gestire richieste/rispostepath: utilità per lavorare con percorsi di file e directoryurl: parsing e manipolazione di URLcrypto: funzionalità crittografiche per hash, cifratura, ecc.
Questi moduli sono sempre disponibili e non richiedono installazione tramite npm. Basta importarli con require().
File System
Accesso al File System
Una delle capacità principali di Node.js è l’accesso al file system della macchina su cui viene eseguito. Questa funzionalità non è disponibile nel browser per motivi di sicurezza, ma in Node.js è essenziale per molte operazioni server-side.
Il modulo fs fornisce metodi per leggere, scrivere e gestire file e directory.
Scrivere un File
Il metodo writeFile() permette di scrivere dati in un file:
const fs = require('fs');
fs.writeFile('data.txt', 'Contenuto del file', (err) => { if (err) { console.error('Errore:', err); return; } console.log('File scritto con successo');});Parametri:
- Primo argomento: percorso del file (relativo o assoluto)
- Secondo argomento: contenuto da scrivere (stringa o Buffer)
- Terzo argomento: callback che viene eseguita al completamento
Se il file non esiste, viene creato. Se esiste già, viene sovrascritto.
Leggere un File
Il metodo readFile() permette di leggere il contenuto di un file:
const fs = require('fs');
fs.readFile('data.txt', 'utf8', (err, data) => { if (err) { console.error('Errore:', err); return; } console.log('Contenuto:', data);});Parametri:
- Primo argomento: percorso del file da leggere
- Secondo argomento: encoding (tipicamente
'utf8'per testo) - Terzo argomento: callback con
erredata
Importante: senza specificare l’encoding, readFile() restituisce un Buffer (oggetto binario) invece di una stringa. Specificare 'utf8' per ottenere testo leggibile.
Operazioni Asincrone
Tutte le operazioni del file system sono asincrone per default. Questo significa che Node.js non blocca l’esecuzione mentre legge o scrive file, permettendo al server di gestire altre richieste contemporaneamente.
Metodi Sincroni (da Evitare)
Esistono versioni sincrone dei metodi (writeFileSync, readFileSync) che bloccano l’esecuzione fino al completamento dell’operazione. Questi metodi sono utili solo per script semplici o operazioni di inizializzazione. In produzione, soprattutto in server web, vanno evitati perché bloccano l’intero processo Node.js.
Server HTTP Base
Creare un Server con Node.js
Il modulo http di Node.js permette di creare server HTTP che possono ricevere richieste e inviare risposte. Questo è il modo più base per creare un server web con Node.js, senza framework aggiuntivi.
Creare un Server
const http = require('http');
const server = http.createServer((req, res) => { res.setHeader('Content-Type', 'text/html'); res.write('<h1>Hello World</h1>'); res.end();});
server.listen(3000, () => { console.log('Server in ascolto su porta 3000');});Spiegazione:
http.createServer()crea un nuovo server HTTP- La funzione passata viene eseguita per ogni richiesta in arrivo
req(request) contiene informazioni sulla richiesta ricevutares(response) permette di configurare e inviare la rispostaserver.listen()avvia il server sulla porta specificata
Una volta avviato, il server rimane in esecuzione e ascolta richieste sulla porta configurata. Per fermarlo, premere Ctrl+C nel terminale.
Parsing del Body (Metodo Manuale)
Quando si riceve una richiesta POST con dati nel body, bisogna parsare manualmente questi dati. Il body arriva in “chunks” (frammenti) per efficienza:
const http = require('http');
const server = http.createServer((req, res) => { let body = [];
// Evento 'data': ogni chunk di dati ricevuto req.on('data', (chunk) => { body.push(chunk); });
// Evento 'end': tutti i dati sono stati ricevuti req.on('end', () => { body = Buffer.concat(body).toString(); const parsedData = parseBody(body); // Logica di parsing personalizzata res.end(JSON.stringify(parsedData)); });});Problemi di questo approccio:
- Parsing manuale complesso e propenso a errori
- Gestione errori verbosa e ripetitiva
- Difficile scalare con molti endpoint diversi
- Nessuna astrazione per routing o middleware
Per questi motivi, nella pratica si preferisce usare framework come Express.js che semplificano notevolmente queste operazioni.
Express.js
Cos’è Express.js
Express.js è il framework più popolare per Node.js. Semplifica la creazione di server web e applicazioni backend, gestendo automaticamente molte operazioni complesse come il parsing del body, il routing e la gestione degli errori.
Installazione
Prima di usare Express, bisogna inizializzare un progetto npm e installare il pacchetto:
npm init -ynpm install expressIl flag -y accetta automaticamente i valori di default per package.json.
Setup Base
Dopo l’installazione, Express può essere importato e utilizzato:
const express = require('express');const app = express();
app.listen(3000, () => { console.log('Server in ascolto su porta 3000');});Chiamare express() restituisce un’applicazione Express che può essere configurata con middleware e routes. app.listen() avvia il server, esattamente come server.listen() nel modulo http nativo.
Middleware
Express è un framework basato su middleware: funzioni che vengono eseguite in sequenza per ogni richiesta. Ogni middleware può modificare la richiesta o la risposta, oppure terminare la catena inviando una risposta.
app.use((req, res, next) => { // Logica middleware console.log('Richiesta ricevuta'); next(); // Passa al middleware successivo});
app.use((req, res, next) => { res.setHeader('Content-Type', 'text/html'); next();});
app.use((req, res) => { res.send('<h1>Hello World</h1>');});Flusso di esecuzione:
- La richiesta arriva al primo middleware registrato con
app.use() - Il middleware esegue la sua logica e chiama
next()per passare al successivo - Il processo continua fino all’ultimo middleware
- Se un middleware invia una risposta con
res.send()ores.json(), la catena si ferma e la risposta viene inviata al client
Il parametro next è una funzione che deve essere chiamata per continuare la catena di middleware. Se non viene chiamata, la richiesta rimane bloccata.
Body Parsing
Una delle funzionalità più utili di Express è il parsing automatico del body delle richieste. Invece di gestire manualmente i chunk di dati, si può usare il middleware body-parser.
Installazione:
npm install body-parserUtilizzo:
const bodyParser = require('body-parser');
// Parsing JSON: per richieste con Content-Type: application/jsonapp.use(bodyParser.json());
// Parsing form data: per dati URL-encoded (form HTML)app.use(bodyParser.urlencoded({ extended: false }));
// Ora req.body contiene automaticamente i dati parsatiapp.post('/submit', (req, res) => { console.log(req.body); // Oggetto JavaScript con i dati parsati res.json({ success: true });});Dopo aver registrato questi middleware, tutti i dati inviati nel body delle richieste vengono automaticamente parsati e resi disponibili in req.body come oggetto JavaScript. L’opzione extended: false usa il parser standard di Node.js, mentre extended: true permette dati più complessi ma è meno sicuro.
Nota: nelle versioni recenti di Express (4.16+), express.json() e express.urlencoded() sono built-in e non richiedono body-parser separato.
Routes
Le routes permettono di definire come rispondere a richieste specifiche basate sul metodo HTTP e sul percorso URL. Express fornisce metodi per ogni metodo HTTP comune.
// GET route: recuperare datiapp.get('/users', (req, res) => { res.json({ users: [] });});
// POST route: creare nuove risorseapp.post('/users', (req, res) => { const newUser = req.body; // Logica per salvare l'utente res.json({ id: 123 });});
// Route con parametri dinamiciapp.get('/users/:id', (req, res) => { const userId = req.params.id; res.json({ user: { id: userId } });});Parametri dinamici: usando :id nel percorso, Express cattura il valore e lo rende disponibile in req.params.id. Questo permette di creare routes flessibili che possono gestire ID diversi.
Metodi disponibili: app.get(), app.post(), app.put(), app.patch(), app.delete(), app.use() (per qualsiasi metodo).
Router Separato
Per progetti più grandi, è buona pratica organizzare le routes in file separati. Express fornisce express.Router() per creare router modulari.
routes/users.js:
const express = require('express');const router = express.Router();
// Queste routes sono relative al percorso base '/users'router.get('/', (req, res) => { res.json({ users: [] });});
router.get('/:id', (req, res) => { res.json({ user: { id: req.params.id } });});
module.exports = router;app.js:
const usersRoutes = require('./routes/users');
// Tutte le routes definite in users.js saranno disponibili sotto /usersapp.use('/users', usersRoutes);Questo approccio permette di:
- Organizzare il codice in moduli logici
- Mantenere
app.jspulito e leggibile - Facilitare la manutenzione e il testing
- Riusare lo stesso router con percorsi base diversi se necessario
Template Engine: EJS
Cos’è un Template Engine
I template engine permettono di generare HTML dinamicamente sul server, inserendo dati JavaScript in file HTML. Questo è utile per creare pagine che cambiano in base ai dati del server senza dover costruire HTML manualmente con stringhe.
Installazione e Configurazione
EJS (Embedded JavaScript) è uno dei template engine più popolari per Express:
npm install ejsDopo l’installazione, bisogna configurare Express per usare EJS:
app.set('view engine', 'ejs');app.set('views', 'views'); // Cartella dove sono i templateLa prima riga dice a Express di usare EJS come engine di default. La seconda specifica la cartella dove cercare i file template.
Template Base
I file template hanno estensione .ejs e contengono HTML con sintassi speciale per inserire dati dinamici:
views/index.ejs:
<!DOCTYPE html><html><head> <title>App</title></head><body> <h1>Hello <%= username %></h1></body></html>La sintassi <%= username %> viene sostituita con il valore della variabile username quando il template viene renderizzato.
Rendering
Per renderizzare un template e inviarlo come risposta:
app.get('/', (req, res) => { res.render('index', { username: 'Vito' });});res.render() prende il nome del template (senza estensione) e un oggetto con i dati da passare al template. Express cerca index.ejs nella cartella views e sostituisce le variabili con i valori forniti.
Sintassi EJS comune:
<%= variabile %>: output del valore (escapato per sicurezza HTML)<% codice %>: esecuzione codice JavaScript (if, loop, ecc.)<%- html %>: output HTML non escapato (usare con cautela)
Il template viene processato sul server e il risultato finale è HTML puro inviato al browser.
REST API
Cos’è una REST API
Una REST API è un’interfaccia che permette di scambiare dati JSON tra client e server usando metodi HTTP standard. A differenza di server che restituiscono HTML, una REST API restituisce solo dati strutturati, lasciando al client la responsabilità di renderizzarli.
Setup Base
Per creare una REST API con Express:
const express = require('express');const app = express();
app.use(express.json()); // Body parsing JSON
app.listen(3000);Il middleware express.json() (o bodyParser.json()) è essenziale per parsare automaticamente i dati JSON inviati nelle richieste POST/PUT.
Endpoint CRUD
Una REST API tipicamente implementa operazioni CRUD (Create, Read, Update, Delete) per ogni risorsa:
// GET: Recuperare tutte le risorseapp.get('/api/items', (req, res) => { res.json({ items: [] });});
// GET: Recuperare una risorsa specificaapp.get('/api/items/:id', (req, res) => { const id = req.params.id; res.json({ item: { id } });});
// POST: Creare una nuova risorsaapp.post('/api/items', (req, res) => { const newItem = req.body; // Logica per salvare l'item nel database res.json({ id: 123, ...newItem });});
// PUT: Aggiornare una risorsa esistenteapp.put('/api/items/:id', (req, res) => { const id = req.params.id; const updates = req.body; // Logica per aggiornare l'item res.json({ id, ...updates });});
// DELETE: Eliminare una risorsaapp.delete('/api/items/:id', (req, res) => { const id = req.params.id; // Logica per eliminare l'item res.status(204).send(); // 204 = No Content (successo senza body)});Convenzioni REST:
- URL plurali per le risorse (
/api/itemsnon/api/item) - Metodi HTTP che descrivono l’operazione
- Risposte JSON consistenti
- Status codes appropriati
Status Codes HTTP
I status codes comunicano il risultato dell’operazione al client:
res.status(200).json({ data }); // Success - operazione riuscitares.status(201).json({ data }); // Created - risorsa creata con successores.status(404).json({ error }); // Not Found - risorsa non trovatares.status(500).json({ error }); // Server Error - errore internores.status(204).send(); // No Content - successo senza contenutoUsare status codes appropriati aiuta il client a gestire correttamente le risposte e gli errori.
CORS
Il Problema delle Richieste Cross-Origin
CORS (Cross-Origin Resource Sharing) è una policy di sicurezza del browser che blocca richieste tra origini diverse. Due URL sono considerati origini diverse se differiscono per protocollo, dominio o porta.
Se il frontend è su localhost:8080 e il backend su localhost:3000, sono considerati origini diverse e il browser bloccherà le richieste tra di loro per default.
Soluzione: Configurare Headers CORS
Per permettere richieste cross-origin, il server deve inviare headers specifici nella risposta:
app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); next();});Headers CORS principali:
Access-Control-Allow-Origin: specifica quali origini possono accedere.'*'permette tutte le origini (usare con cautela in produzione)Access-Control-Allow-Methods: lista dei metodi HTTP permessiAccess-Control-Allow-Headers: lista degli headers che il client può inviare
Preflight Requests: per alcune richieste (come POST con JSON), il browser invia prima una richiesta OPTIONS per verificare i permessi. Il server deve rispondere correttamente a questa richiesta, altrimenti la richiesta effettiva verrà bloccata. Assicurarsi di includere OPTIONS nei metodi permessi o gestire esplicitamente le richieste OPTIONS.
MongoDB
Cos’è MongoDB
MongoDB è un database NoSQL che memorizza dati in formato JSON-like (documenti). Si integra particolarmente bene con Node.js perché entrambi lavorano nativamente con oggetti JavaScript.
Installazione Driver
Per connettersi a MongoDB da Node.js, serve il driver ufficiale:
npm install mongodbConnessione al Database
Il driver MongoDB permette di connettersi a un database MongoDB (locale o cloud) e eseguire operazioni:
const mongodb = require('mongodb');const MongoClient = mongodb.MongoClient;
const connectionURL = 'mongodb+srv://username:password@cluster.mongodb.net/database';
const client = new MongoClient(connectionURL);
client.connect((err, client) => { if (err) { console.error('Errore connessione:', err); return; }
const db = client.db('database-name'); // Operazioni database qui});La connection string contiene le credenziali e l’indirizzo del database. Per MongoDB Atlas (cloud), la stringa include username, password e cluster address. Il metodo connect() è asincrono e accetta una callback che viene eseguita quando la connessione è stabilita o se si verifica un errore.
Struttura: Database, Collection, Documenti
MongoDB organizza i dati in:
- Database: contenitore principale (equivalente a un database SQL)
- Collection: gruppo di documenti simili (equivalente a una tabella SQL)
- Documento: singolo oggetto JSON (equivalente a una riga SQL)
Inserire Documenti
Per inserire un nuovo documento in una collection:
client.connect((err, client) => { const db = client.db('locations'); const collection = db.collection('user-locations');
collection.insertOne({ address: 'Via Roma 1', coords: { lat: 41.9028, lng: 12.4964 } }, (err, result) => { if (err) { console.error('Errore inserimento:', err); return; } console.log('ID inserito:', result.insertedId); });});insertOne() inserisce un singolo documento. Se la collection non esiste, viene creata automaticamente. MongoDB genera automaticamente un _id univoco per ogni documento inserito, disponibile in result.insertedId.
Trovare Documenti
Per cercare documenti in una collection:
// Trovare un documento specificocollection.findOne( { _id: new mongodb.ObjectId('id-stringa') }, (err, doc) => { if (err) { console.error('Errore ricerca:', err); return; } console.log('Documento trovato:', doc); });
// Trovare più documenti che corrispondono a critericollection.find({ address: 'Via Roma' }).toArray((err, docs) => { console.log('Documenti trovati:', docs);});findOne() restituisce il primo documento che corrisponde ai criteri, o null se nessuno corrisponde. find() restituisce un cursor che può essere convertito in array con toArray().
Nota importante: gli ID in MongoDB sono di tipo ObjectId, non stringhe semplici. Quando si cerca per ID, bisogna convertire la stringa in ObjectId usando new mongodb.ObjectId(idString). Se si prova a cercare con una stringa normale, la query non troverà il documento anche se l’ID corrisponde.
Esempio Completo: Route con MongoDB
Ecco un esempio completo che combina Express routes con operazioni MongoDB:
const express = require('express');const mongodb = require('mongodb');const router = express.Router();
const MongoClient = mongodb.MongoClient;const connectionURL = 'mongodb+srv://username:password@cluster.mongodb.net/locations';
// POST: Salvare una location nel databaserouter.post('/location', (req, res) => { MongoClient.connect(connectionURL, (err, client) => { if (err) { return res.status(500).json({ error: 'Database connection failed' }); }
const db = client.db('locations'); const collection = db.collection('user-locations');
collection.insertOne({ address: req.body.address, coords: { lat: req.body.lat, lng: req.body.lng } }, (err, result) => { if (err) { return res.status(500).json({ error: 'Errore salvataggio' }); } res.json({ locId: result.insertedId }); }); });});
// GET: Recuperare una location dal databaserouter.get('/location/:lid', (req, res) => { const locationId = req.params.lid;
MongoClient.connect(connectionURL, (err, client) => { if (err) { return res.status(500).json({ error: 'Database connection failed' }); }
const db = client.db('locations'); const collection = db.collection('user-locations');
collection.findOne( { _id: new mongodb.ObjectId(locationId) }, (err, doc) => { if (err || !doc) { return res.status(404).json({ message: 'Not found' }); } res.json({ address: doc.address, coordinates: doc.coords }); } ); });});
module.exports = router;Questo esempio mostra come:
- Connettersi al database per ogni richiesta (in produzione, si preferisce riutilizzare la connessione)
- Gestire errori di connessione e operazioni
- Convertire l’ID stringa in
ObjectIdper le query - Restituire status codes appropriati
- Strutturare le routes in un file separato
Gestione Errori
La gestione degli errori è cruciale in un’applicazione production-ready. Ecco un esempio migliorato:
router.get('/location/:lid', (req, res) => { let locationId;
// Validare e convertire l'ID prima di usarlo try { locationId = new mongodb.ObjectId(req.params.lid); } catch (error) { // Se l'ID non è valido, ObjectId lancerà un errore return res.status(500).json({ message: 'Invalid id' }); }
MongoClient.connect(connectionURL, (err, client) => { if (err) { return res.status(500).json({ error: 'Database error' }); }
const db = client.db('locations'); const collection = db.collection('user-locations');
collection.findOne({ _id: locationId }, (err, doc) => { if (err) { return res.status(500).json({ error: 'Query error' }); } if (!doc) { return res.status(404).json({ message: 'Not found' }); } res.json({ address: doc.address, coordinates: doc.coords }); }); });});Punti importanti:
- Validare l’ID prima di usarlo nelle query (usare
try/catchperObjectId) - Gestire errori di connessione separatamente dagli errori di query
- Distinguere tra “documento non trovato” (404) e “errore del server” (500)
- Restituire sempre una risposta, anche in caso di errore
Struttura Progetto Tipica
Organizzazione Consigliata
Per progetti Node.js più grandi, è importante organizzare il codice in una struttura chiara e modulare:
project/├── app.js # Entry point principale├── package.json # Dipendenze e configurazione npm├── routes/ # Routes organizzate per risorsa│ ├── users.js # Routes relative agli utenti│ └── locations.js # Routes relative alle locations├── views/ # Template EJS (se si usa server-side rendering)│ └── index.ejs└── node_modules/ # Dipendenze installate (non committare)Questa struttura separa le responsabilità: app.js contiene la configurazione generale, mentre le routes sono organizzate in file separati per risorsa.
app.js Esempio Completo
Il file principale tipicamente configura Express, registra middleware globali e monta le routes:
const express = require('express');const bodyParser = require('body-parser');const usersRoutes = require('./routes/users');const locationsRoutes = require('./routes/locations');
const app = express();
// Middleware globali: applicati a tutte le richiesteapp.use(bodyParser.json());app.use(bodyParser.urlencoded({ extended: false }));
// CORS: permette richieste cross-originapp.use((req, res, next) => { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); next();});
// Routes: montate con percorsi base specificiapp.use('/api/users', usersRoutes);app.use('/api/locations', locationsRoutes);
app.listen(3000, () => { console.log('Server running on port 3000');});L’ordine è importante: i middleware vengono eseguiti nell’ordine in cui sono registrati. Le routes vengono montate dopo i middleware globali, così ogni richiesta passa prima attraverso i middleware (parsing body, CORS) e poi viene gestita dalla route appropriata.
Riepilogo
-
Node.js: ambiente JavaScript lato server. Stessa sintassi del browser ma API diverse (file system, HTTP server, database).
-
Moduli:
require()per importare,module.exportsper esportare. Moduli core disponibili senza installazione. -
File System:
fs.writeFile()efs.readFile()per operazioni su file. Operazioni asincrone con callback. -
Server HTTP:
http.createServer()per server base. Express.js semplifica la creazione di server web con middleware e routing. -
Express.js: framework basato su middleware.
app.use()per middleware globali,app.get/post()per routes,app.listen()per avviare il server. -
Body Parsing:
body-parserper parsare JSON e form data. Dati disponibili inreq.bodydopo il parsing. -
Routes: organizzare routes in file separati con
express.Router(). Esportare router e importarlo inapp.jsconapp.use(). -
REST API: pattern per scambiare dati JSON. Endpoint organizzati per risorsa (
/api/items), metodi HTTP per operazioni (GET, POST, PUT, DELETE). -
CORS: configurare headers per permettere richieste cross-origin. Necessario quando frontend e backend sono su origini diverse.
-
MongoDB: driver
mongodbper connettersi e operare su database.insertOne()per inserire,findOne()per cercare. ID sonoObjectId, non stringhe.