- Express.js Basics
- Express.js HOME
- Express.js Introduction
- Express.js Installation
- Express.js Basic App
- Express.js Routing
- Basics Routing
- Route Parameters
- Handling Query Strings
- Router Middleware
- Middleware
- What is Middleware?
- Application-Level Middleware
- Router-Level Middleware
- Built-In Middleware
- Error-Handling Middleware
- Third-Party Middleware
- Express.js HTTP
- Handling GET Requests
- Handling POST Requests
- Handling PUT Requests
- Handling DELETE Requests
- Templating Engines
- Using Templating Engines
- Setting Up EJS
- Setting Up Handlebars
- Setting Up Pug
- Request/Response
- Request Object
- Response Object
- Handling JSON Data
- Handling Form Data
- Static Files
- Serving Static Files
- Setting Up Static Folders
- Managing Assets
- Express.js Advanced
- Middleware Stack
- CORS in Express.js
- JWT Authentication
- Session Handling
- File Uploads
- Error Handling
- Databases
- Express.js with MongoDB
- MongoDB CRUD Operations
- Express.js with MySQL
- MySQL CRUD Operations
- Deployment
- Deploying Express.js Apps to Heroku
- Deploying Express.js Apps to AWS
- Deploying Express.js Apps to Vercel
Express.js Serving Static Files
In a modern web application, not everything is dynamic logic or database queries. You frequently need to deliver "static" assets—files that don't change while the app is running, such as images, CSS stylesheets, client-side JavaScript, and even plain HTML files. Express.js makes this incredibly efficient with a built-in middleware function that handles these requests automatically, saving you from writing custom routes for every single image or script in your project.
Key Features of Serving Static Files
- Built-in Middleware: You don't need to install external packages;
express.staticis included in the core Express framework. - Efficient Streaming: Express handles file streaming and basic headers (like Content-Type) automatically based on the file extension.
- Organized Structure: It encourages a clean project layout by separating your logic (routes/controllers) from your assets (public files).
- Mounting Paths: You can create "virtual" paths, allowing you to hide your actual folder structure from the public.
Components of Serving Static Files
Using express.static Middleware
The express.static middleware is the workhorse here. When a request comes in, Express checks if the requested path matches a file in the specified directory. If it finds a match, it serves the file; if not, it passes the request to the next middleware in the stack.
Example:
const express = require('express');
const app = express();
// Serve static files from the 'public' directory
app.use(express.static('public'));
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
public/style.css and you use app.use(express.static('public')), the URL is http://localhost:3000/style.css, NOT /public/style.css.
Serving Files from a Specific Subfolder (Virtual Paths)
Sometimes you want your URLs to look different from your actual folder names. For instance, you might want all image requests to start with /images, even if they are stored in a folder named public/media/uploads. This is called a "Virtual Path Prefix."
Example:
app.use('/static', express.static('public'));
Now, to access a file located at public/logo.png, the user would visit http://localhost:3000/static/logo.png.
/static or /assets). This prevents naming collisions between your static files and your API routes (e.g., having a file named user.json in your public folder vs an API route at /user).
Setting Up a Custom Static Folder with Absolute Paths
While using relative paths works most of the time, it can cause issues if you launch your Express app from a different directory. To make your application more robust, use the Node.js path module and __dirname.
Example:
const path = require('path');
// Use an absolute path for reliability
app.use('/assets', express.static(path.join(__dirname, 'assets')));
path.join(__dirname, 'folder') ensures your application works correctly regardless of which directory you are in when you run the node app.js command.
Cache-Control Headers
Static files don't change often. You can tell the user's browser to store these files locally (cache them) so they don't have to download them again on the next visit. This significantly speeds up your site's load time.
Example:
const oneDay = 86400000; // Milliseconds in a day
app.use(express.static('public', {
maxAge: oneDay,
etag: true // Helps with cache validation
}));
style.css?v=1.2).
Serving Multiple Static Folders
You aren't limited to just one directory. Express allows you to define multiple static directories. Express will search them in the order they are defined in your code.
Example:
app.use(express.static('public'));
app.use(express.static('internal-assets'));
If a request for /main.js comes in, Express first looks in public/. If it isn't there, it checks internal-assets/.
Complete Real-World Example
Here is how a standard project setup looks, incorporating best practices and the path module for cross-platform compatibility.
const express = require('express');
const path = require('path');
const app = express();
// 1. Serve general assets (CSS, JS) with a virtual prefix
app.use('/static', express.static(path.join(__dirname, 'public')));
// 2. Serve user-uploaded images from a different location
app.use('/uploads', express.static(path.join(__dirname, 'user_content/images')));
// 3. Example route for the home page
app.get('/', (req, res) => {
res.send('<h1>Welcome!</h1><p>Check out our <a href="/static/style.css">Stylesheet</a></p>');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
Summary
The express.static middleware is an essential tool for any web developer. It provides a simple, high-performance way to deliver the visual and interactive parts of your site. By using absolute paths with path.join, setting up virtual prefixes for better organization, and implementing caching strategies, you can build a fast and professional asset delivery system for your Express.js applications.