Node.js Static Files

Static files never change while the server runs. Images, stylesheets, browser scripts, fonts, and plain HTML pages all fit this group. Express serves these files with one built-in function.

Static and Dynamic Content

A static file is like a printed poster. The server hands out the same copy to everyone. Dynamic content is like a cooked meal. The server prepares it fresh for each visitor.

 Browser asks for /logo.png
        |
        v
 +----------------+      +------------------+
 | Express server | ---> | public/logo.png  |
 +----------------+      +------------------+
        |
        v
 Browser receives the file unchanged

Set Up a Public Folder

Create a folder named public and place your files inside.

my-app/
  index.js
  public/
    index.html
    about.html
    css/
      style.css
    images/
      logo.png
    js/
      app.js

Serve the Folder

Call express.static with the folder name inside app.use.

const express = require("express");
const app = express();

app.use(express.static("public"));

app.listen(3000, () => console.log("Server runs on port 3000"));

Express now answers these addresses.

  • http://localhost:3000/ returns public/index.html.
  • http://localhost:3000/about.html returns public/about.html.
  • http://localhost:3000/css/style.css returns the stylesheet.
  • http://localhost:3000/images/logo.png returns the image.

The folder name public never appears in the address. Express treats the folder as the site root.

Use an Absolute Path

A relative folder name depends on where you start the program. An absolute path works from any location.

const path = require("path");

app.use(express.static(path.join(__dirname, "public")));

Add a Prefix

A prefix adds a virtual folder name to the address.

app.use("/assets", express.static("public"));

Visitors now reach the logo at /assets/images/logo.png.

Address in browser            File on disk
/assets/images/logo.png  -->  public/images/logo.png

Serve Several Folders

Express tries each static folder in the order you list them. The first match wins.

app.use(express.static("public"));
app.use(express.static("uploads"));

Link Files in HTML

Write addresses that start with a slash. These addresses always begin at the site root.

<link rel="stylesheet" href="/css/style.css">
<img src="/images/logo.png" alt="Company logo">
<script src="/js/app.js"></script>

Control Browser Caching

Caching lets the browser keep a copy of a file and skip repeat downloads. Pages load faster and the server works less.

app.use(express.static("public", {
  maxAge: "7d",
  etag: true,
  index: "index.html"
}));
  • maxAge sets how long the browser keeps the file.
  • etag lets the browser check whether the file changed.
  • index names the default file for a folder address.

Mix Static Files with Routes

Place the static line above your routes. Express then serves matching files before it checks routes.

app.use(express.static("public"));

app.get("/api/time", (req, res) => {
  res.json({ time: new Date().toISOString() });
});

Send a Single File

Use res.sendFile when one route needs to return one file.

app.get("/help", (req, res) => {
  res.sendFile(path.join(__dirname, "public", "help.html"));
});

Safety Tips

  • Place only public files inside the static folder.
  • Keep passwords, configuration files, and source code outside the folder.
  • Avoid serving your whole project folder.

Common Problems

404 Not Found

Check the folder name, file name, and capital letters. Linux servers treat Logo.png and logo.png as different files.

Styles Do Not Load

Open the browser developer tools and read the Network tab. A wrong link path shows a red entry.

Practice Tasks

  • Create a public folder with a home page, a stylesheet, and one image.
  • Serve the folder and open the page in your browser.
  • Add the /assets prefix and update your links.