Routing and caching
How a static web app answers requests — the single-page app fallback, the 404 page, the cache presets and their exact headers, redirects and response headers.
All of these settings apply without packaging the site again: a change takes effect within seconds.
How a request is answered
Redirects are checked before these steps.
- A path that matches a file serves the file; a path that matches a directory serves the
directory's
index.html. - Otherwise, with a single-page app fallback set, the fallback file is served with status 200.
- Otherwise the answer is 404, with the 404 page when one is set.
Requests for asset files never fall back: a missing .js, .css, image or font file answers 404
instead of the fallback page. Asset files are those ending in .js, .mjs, .css, .woff,
.woff2, .ttf, .otf, .eot, .svg, .png, .jpg, .jpeg, .gif, .webp, .avif, .ico
or .map.
Single-page app fallback
| Where | Setting | Values |
|---|---|---|
| Create wizard | Single-page app routing | On (the default) serves /index.html; off serves 404 |
| Configuration → Routing | Single-page app fallback | An absolute path such as /index.html; empty turns the fallback off |
| API, CLI | navigationFallback |
Same as above |
| API, CLI | navigationFallbackExclude |
Paths that keep answering 404 instead of falling back, such as /api/* |
404 page
404 page (notFoundPage) is an absolute path such as /404.html. It is served, with status
404, for every path that matches no file and does not fall back. Empty serves the web server's
own 404 page.
The fallback file and the 404 page must exist in the deployed site. When one does not, the changed routing does not start: the site keeps its previous routing and shows Degraded.
Cache presets
| Preset (API value) | Hashed asset files | Other asset files | /index.html |
Everything else |
|---|---|---|---|---|
Hashed assets (recommended) (HashedAssetsImmutable) |
public, max-age=31536000, immutable |
none | no-cache |
none |
Cache all assets (Aggressive) |
public, max-age=31536000, immutable |
public, max-age=31536000, immutable |
no-cache |
none |
No cache headers (Off) |
none | none | none | none |
The values are the Cache-Control header; "none" means the response carries no
Cache-Control header.
- A hashed asset file has a hash of at least eight letters, digits,
_or-between two dots right before its extension, such asapp.4f3c2b1a.js. A hash joined with a hyphen, as inindex-4f3c2b1a.js, does not count. max-age=31536000is one year. Under Cache all assets, returning visitors keep an unhashed file such aslogo.pngfor up to a year, even after you deploy a new one.no-cachemakes browsers check with the site before reusing/index.html, so a deployment shows at once. It applies when/index.htmlis requested directly, for/, and when it is served as the fallback.
Other rules
- Files and directories whose names begin with a dot are refused, except under
/.well-known/. - Text responses — HTML, CSS, JavaScript, JSON, XML, SVG, plain text — are compressed with gzip.
- Plain HTTP is redirected to HTTPS.
Redirects and response headers
The portal does not edit these; set them through the API or with stsh swa update. They apply
without a redeploy, like the rest of the routing.
redirects is a list of rules. A from without * matches that one path and wins over every
other rule. Among * rules, the longest matching prefix wins, whatever their order in the list.
| Field | Meaning |
|---|---|
from |
An absolute path; a trailing * matches every path that starts with it |
to |
An absolute path or a full http:// or https:// URL. Addresses starting with // are refused |
statusCode |
301 (the default), 302, 307 or 308 |
headers adds a response header to matching paths.
| Field | Meaning |
|---|---|
path |
An absolute path, a trailing * matching a prefix; /* (the default) matches everything |
name |
The header name: letters, digits and - |
value |
The header value, on one line |
Paths may use letters, digits and / . - _ ~ @ :; they may not contain ... Two redirects that
match the same paths are refused.
A * redirect does not catch every path under its prefix. Requests for asset files (the
extensions in How a request is answered) are served as files, or answer 404,
instead of being redirected while Cache all assets or a single-page app fallback is set. With
Hashed assets and no fallback, this applies only to hashed asset files; other asset files are
redirected. Paths with a segment that begins with a dot are refused rather than redirected.
Caution
A header whose
pathis anything other than/*is not sent on the pages under that path. It is sent only on asset files under the path — all of them while Cache all assets or a single-page app fallback is set, only hashed ones with Hashed assets and no fallback, none with No cache headers and no fallback — and on the responses of redirects, the fallback file, the 404 page and/index.htmlwhen their own path matches it. A header on/admin/*, for example, does not reach/admin/index.htmlor any other page there. Headers on/*are sent on every response except under/.well-known/; use/*for security headers such asX-Frame-OptionsorContent-Security-Policy.
stsh swa update my-site -g my-resource-group \
--set 'redirects=[{"from":"/blog/*","to":"https://blog.example.com/","statusCode":301}]' \
--set 'headers=[{"path":"/*","name":"X-Frame-Options","value":"DENY"}]'