Blazor WebAssembly
A Blazor WebAssembly app is a folder of static files, so nothing is special-cased for its sake. This is the static file handler with the three settings a Blazor publish needs — and getting any of them wrong produces a blank page and a stack trace from inside the runtime rather than an obvious error.
app.UseBlazorWebAssembly("./wwwroot");app.MapGet("/api/readings", …); // the app's own API, alongside itFor the packaged case — a MAUI or single-file build with no wwwroot on disk:
app.UseBlazorWebAssembly(typeof(App).Assembly, "MyApp.wwwroot");What it arranges
Section titled “What it arranges”The single-page fallback. A Blazor route like /counter exists only in the client-side router, so
a reload of that URL has to return index.html. The fallback is still restricted to requests that
look like navigations, so a missing .js 404s honestly.
Precompressed assets. A publish emits .br and .gz beside every file, compressed once at
maximum effort. Serving those beats recompressing 20-odd megabytes per request at a level chosen for
speed. ServePrecompressedFiles is on, and the disk source is configured to look for br then
gzip.
Cache policy. Everything under _framework and _content is content-fingerprinted by the
publish, so it is served public, max-age=31536000, immutable. The entry document is no-cache —
it keeps the same URL by definition, and caching it is how a deploy silently fails to reach anyone.
no-cache rather than no-store: the browser may keep its copy, it just has to revalidate, and with
an ETag that is a conditional request answered by a 304.
You can still adjust everything through the optional configure callback, which runs after those
defaults are applied.
Content types
Section titled “Content types”Only one thing was ever actually missing when this was verified against a real publish — 26 MB of
assets and 36 wasm assemblies, loaded in Chrome and interactive. .dat, the ICU globalization data,
had no content type, and an unknown extension is not served, so the runtime died on a 404 before it
started.
.dat, .blat, .webcil, .dll, .pdb and .webmanifest are in the built-in map. If a publish
ever emits something else new, add it rather than turning on ServeUnknownFileTypes:
app.UseBlazorWebAssembly("./wwwroot", o => o.ContentTypeOverrides[".xyz"] = "application/octet-stream");Why you would do this
Section titled “Why you would do this”The interesting deployment is not a web server. It is a Blazor app served by the device it talks to: a MAUI app hosting its own UI, an appliance with no cloud, a piece of equipment whose configuration page is only reachable on the LAN. Pair it with a tunnel and the same app is reachable from anywhere without any of it being deployed anywhere.


