Serving front-end builds and assets from NGINX is fast and common, and root vs alias mistakes cause most 404s.
root sets the directory that the full URI is appended to: with root /var/www/site;, a request for /img/logo.png reads /var/www/site/img/logo.png.
alias replaces the matched location prefix instead: in location /static/ { alias /srv/assets/; }, /static/app.js reads /srv/assets/app.js. Keep the trailing slashes consistent on both, or paths get glued together wrongly.
index index.html; names the file served for a request ending in /.
try_files checks alternatives in order and uses the first that exists; the last parameter is a fallback URI (or =404):
try_files $uri $uri/ =404;: the file, then a directory with an index, otherwise 404.try_files $uri /index.html;: the classic single-page application setup: unknown paths serveindex.htmlso the client-side router can handle them.
Other useful directives for static content:
expires 30d;oradd_header Cache-Control ...for browser caching of fingerprinted assets.autoindex on;for a directory listing (rarely wanted in production).- MIME types come from
mime.types; a wrongContent-Typeusually means it isn't included.
NGINX uses the sendfile system call to send files without copying them through user space, which makes static serving very cheap.
Example
server {
listen 80;
server_name app.example.com;
root /var/www/app/dist; # /about -> /var/www/app/dist/about
index index.html;
location / {
try_files $uri $uri/ /index.html; # SPA fallback
}
location /assets/ {
expires 1y; # fingerprinted, safe to cache long
access_log off;
}
location /downloads/ {
alias /srv/files/; # /downloads/a.zip -> /srv/files/a.zip
}
}Remember
- root appends the full URI; alias replaces the location prefix
- try_files tries files in order, then falls back
- try_files $uri /index.html serves single-page apps
Watch out for
- Using root where alias was meant: /downloads/a.zip becomes /srv/files/downloads/a.zip.