# Serving Static Files and Single-Page Apps — Nginx

Source: https://www.skillbyai.com/en/nginx/s-static

> Serve files efficiently with root, alias, try_files and caching headers.

## Files straight from disk

NGINX serves static files very efficiently. **`root /var/www/site;`** maps a request URI to a path by **appending** the full URI: `/images/a.png` becomes `/var/www/site/images/a.png`. **`alias`** inside a location **replaces** the matched prefix: `location /media/ { alias /data/uploads/; }` maps `/media/a.png` to `/data/uploads/a.png` (keep trailing slashes consistent on both). **`index`** lists files to try for directory requests. **`try_files`** checks files in order and falls back to the last argument: `try_files $uri $uri/ =404;` for normal sites, and `try_files $uri $uri/ /index.html;` for **single-page applications**, so client-side routes such as `/orders/42` load the app shell instead of a 404. Enable `sendfile on;` for kernel-level file transfer. Set caching headers with **`expires`** or `add_header Cache-Control`: long-lived and `immutable` for fingerprinted assets, short or `no-cache` for `index.html`. Never point `root` at a directory containing source code or secrets.

## A single-page app with long-cached assets

The HTML is always revalidated; hashed assets are cached for a year.

```nginx
server {
    listen 80;
    server_name app.example.com;
    root /var/www/app/dist;
    index index.html;

    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, max-age=31536000, immutable";
        try_files $uri =404;
    }

    location /uploads/ {
        alias /data/uploads/;              # /uploads/a.png -> /data/uploads/a.png
    }

    location / {
        add_header Cache-Control "no-cache";
        try_files $uri $uri/ /index.html;  # client-side routes load the app
    }
}
```

## root inside location is usually a smell

Set `root` once at server level and let locations inherit it. Repeating `root` in many locations is error-prone; use `alias` only when a location must map to a different directory.

**Quiz:** With `location /media/ { alias /data/uploads/; }`, which file serves /media/cat.png?

- [x] /data/uploads/cat.png
- [ ] /data/uploads/media/cat.png
- [ ] /media/cat.png
- [ ] /var/www/media/cat.png

*Answer:* /data/uploads/cat.png. alias replaces the matched prefix, whereas root would append the whole URI.
