Menu

express.static: servire file statici con Express

app.use(express.static(path.join(__dirname, 'public'))) serve ogni file della cartella public all'URL corrispondente: public/style.css risponde a /style.css. Aggiungi un path di montaggio per servirli sotto un prefisso.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

express.static è il middleware integrato che serve i file di una cartella. app.use(express.static(path.join(__dirname, 'public'))) rende ogni file di public disponibile allo stesso path nell'URL: public/style.css risponde a /style.css e public/index.html risponde a /. Express imposta il Content-Type in base all'estensione del file e, quando nessun file corrisponde, passa la richiesta alle tue route invece di rispondere 404.

La risposta a GET /style.css è il testo del file, con Content-Type: text/css; charset=utf-8 nella scheda Headers. Invia GET / per ottenere index.html, poi GET /api/time: quel file non esiste, quindi risponde la route.

Perché il path della cartella ha bisogno di __dirname

express.static('public') risolve 'public' rispetto alla cartella da cui hai avviato Node, non a quella in cui si trova server.js. Funziona quando esegui node server.js dentro il progetto e si rompe quando un process manager o uno script avvia l'app da un'altra posizione:

// project/server.js uses express.static('public')
// cd project && node server.js      -> serves project/public
// node project/server.js            -> looks for ./public, every file is 404

path.join(__dirname, 'public') è la cartella accanto al file che contiene la riga, ovunque sia stato avviato Node. In un modulo ES usa path.join(import.meta.dirname, 'public') (Node 20.11 e successivi). La pagina sul modulo path spiega nel dettaglio __dirname e path.join.

Servire file sotto un prefisso

Passa prima un path di montaggio per servire la cartella sotto un prefisso dell'URL. Il prefisso non fa parte del path del file sul disco:

GET /assets/app.js restituisce console.log("hi"); come text/javascript, e GET /assets/img/dot.svg arriva nella sottocartella. Invia GET /app.js senza il prefisso: è un 404, perché i file esistono solo sotto /assets. Usa un prefisso per evitare che gli URL dei file si scontrino con le route della tua API.

Header di cache con maxAge

Di default Express invia Cache-Control: public, max-age=0, quindi i browser chiedono conferma al server a ogni uso (e ricevono un rapido 304 Not Modified quando il file non è cambiato, grazie all'header ETag). Per i file il cui nome cambia a ogni build, come app.3f9a1c.js, di' ai browser di tenerli:

Apri la scheda Headers: ora Cache-Control è public, max-age=604800, sette giorni in secondi. index: false disattiva l'invio di index.html per gli URL delle cartelle. Altre opzioni utili sono extensions: ['html'], che permette a /about di trovare about.html, e dotfiles, che di default è 'ignore' così file come .env non vengono mai serviti.

Single page app: tornare a index.html

Un'app React o Vue costruita per il routing lato client ha bisogno che ogni path sconosciuto restituisca index.html, così un reload su /settings non dà 404. Metti il fallback dopo express.static e le route dell'API:

app.use(express.static(path.join(__dirname, 'dist')));
app.use('/api', apiRouter);

// Express 5 wildcard syntax
app.get('/*splat', (req, res) => {
    res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});

Errori comuni

Mettere il nome della cartella nell'URL. Con app.use(express.static('public')) l'URL è /style.css, non /public/style.css. Se vuoi /public nell'URL, montala: app.use('/public', express.static(...)).

Collegare i file con path relativi nell'HTML. <link href="style.css"> nella pagina /blog/post chiede /blog/style.css. Inizia il path con una barra: /style.css.

Mettere segreti nella cartella statica. Tutto quello che contiene è pubblico. Tieni fuori file di configurazione, chiavi e codice sorgente.

Domande frequenti

Posso usare express.static più di una volta?

Sì. Registrane uno per cartella; Express le controlla nell'ordine in cui le hai aggiunte e serve il primo file che trova. Dai a ciascuna un path di montaggio diverso quando le cartelle possono contenere file con lo stesso nome.

Express deve servire i file statici in produzione?

Per app piccole va bene. Con molto traffico, metti davanti una CDN o un reverse proxy come Nginx, che serve i file più velocemente e li tiene in cache più vicino agli utenti, e lascia a Express l'API.

Come invio un file specifico da una route?

Usa res.sendFile(path.join(__dirname, 'files', 'report.pdf')). Il path deve essere assoluto (oppure passi l'opzione root). Usa invece res.download() quando il browser deve salvare il file invece di mostrarlo.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

Inizia