How to serve static files and improve performance in Express.js?
Static Files & Performance in Express.js
Serving static files (HTML, CSS, JS, images) efficiently and compressing responses are fundamental to Express.js performance.
Serving Static Files
express.static() is Express's built-in middleware for serving static assets:
js
const express = require('express');
const path = require('path');
const app = express();
// Serve everything in the 'public' folder
app.use(express.static('public'));
// With absolute path (recommended)
app.use(express.static(path.join(__dirname, 'public')));
// With URL prefix
app.use('/static', express.static(path.join(__dirname, 'public')));
// → http://localhost:3000/static/style.csspublic/
index.html → GET /
style.css → GET /style.css
js/app.js → GET /js/app.js
images/logo.png → GET /images/logo.pngStatic Middleware Options
js
app.use(express.static('public', {
maxAge: '1d', // cache for 1 day (browser caching)
etag: true, // enable ETag for cache validation
lastModified: true, // enable Last-Modified header
index: 'index.html', // default file for directories
dotfiles: 'ignore', // hide .env, .git files
extensions: ['html'], // try adding .html extension
}));Response Compression
bash
npm install compressionjs
const compression = require('compression');
// Compress all responses (gzip / deflate)
app.use(compression());
// With options
app.use(compression({
level: 6, // compression level 1-9 (6 is default)
threshold: 1024, // only compress responses > 1KB
filter: (req, res) => {
// Don't compress if client requests no compression
if (req.headers['x-no-compression']) return false;
return compression.filter(req, res);
}
}));Cache-Control Headers
js
// Immutable assets (hashed filenames like app.abc123.js)
app.use('/static', express.static('public', {
maxAge: '1y', // cache for 1 year
immutable: true // tell browser file will never change
}));
// Dynamic HTML — never cache
app.use((req, res, next) => {
if (req.path.endsWith('.html')) {
res.set('Cache-Control', 'no-cache, no-store, must-revalidate');
}
next();
});Serve a React/Vue Build
js
// Serve React/Vue build from Express
app.use(express.static(path.join(__dirname, 'client/build')));
// For React Router — send index.html for all non-API routes
app.get('*', (req, res) => {
if (!req.path.startsWith('/api')) {
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
}
});Multiple Static Directories
js
// Express checks directories in order
app.use(express.static('public'));
app.use(express.static('uploads'));
app.use(express.static('node_modules/bootstrap/dist'));Performance Tips
| Technique | Impact |
|---|---|
Enable compression | Reduce response size 60-80% |
Set Cache-Control headers | Reduce repeated requests |
| Use CDN for assets | Global low-latency delivery |
| Serve from nginx | Far faster than Node.js for static |
| Use HTTP/2 | Multiplexing, header compression |
| Bundle & minify assets | Fewer and smaller requests |
Production: Use nginx
In production, serve static files from nginx in front of Express:
nginx
# nginx.conf
location /static/ {
root /var/www/myapp/public;
expires 1y;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://localhost:3000;
}This offloads static file serving from Node.js entirely.
Summary
Use express.static() to serve files and add compression middleware to gzip responses. Set appropriate Cache-Control headers for long-lived assets. In production, offload static files to nginx or a CDN for maximum performance.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.