Serve a directory of files with root and index, match URLs with location blocks, add an SPA fallback with try_files, and shrink responses with gzip.
The simplest job: hand visitors files from a folder on disk. root sets the base directory, and Nginx appends the request path to it — a request for /css/app.css is served from /var/www/site/css/app.css. index names the file to return for a directory request like "/". Nginx serves static files extremely fast, so this is the right tool for HTML, CSS, JS, and images.
server {
listen 80;
server_name example.com;
root /var/www/site; # files live here
index index.html; # "/" serves /var/www/site/index.html
location / {
try_files $uri $uri/ =404; # file? directory? else 404
}
}location decides which block handles a URL. A plain prefix (location /images/) matches any path starting with it; = means an exact match; and a single-page app needs a catch-all that falls back to index.html so client-side routing works. try_files tries each option in order and uses the first that exists — here, the real file, then the folder, then index.html.
# Long-cache static assets (their names are fingerprinted):
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Single-page app: unknown paths fall back to index.html
location / {
try_files $uri $uri/ /index.html;
}Text files — HTML, CSS, JS, JSON — compress to a fraction of their size, so turning on gzip makes pages load faster for almost no cost. Enable it in the http block (or a server block) and list the types to compress. Already-compressed formats like images and video are skipped automatically, so you only list text-based types.
# In the http { } block of /etc/nginx/nginx.conf
gzip on;
gzip_min_length 1024; # don't bother compressing tiny responses
gzip_types
text/plain
text/css
application/javascript
application/json
image/svg+xml;