Service Worker Settings
Everything you can configure in service-worker.js before importing the Bswup engine.
self.assetsInclude = [/\/data\.db$/];
self.assetsExclude = [/\.scp\.css$/, /weather\.json$/];
self.defaultUrl = '/';
self.prohibitedUrls = [/\/admin\//];
self.serverHandledUrls = [/\/api\//];
self.serverRenderedUrls = [/\/privacy$/];
self.externalAssets = [
{
"url": "/"
},
{
"url": "https://www.googletagmanager.com/gtag/js?id=G-G123456789"
}
];
self.assetsUrl = '/service-worker-assets.js';
self.noPrerenderQuery = 'no-prerender=true';
self.cacheVersion = '2026.05.31-abc1234';
self.caseInsensitiveUrl = true;
self.ignoreDefaultInclude = true;
self.ignoreDefaultExclude = true;
self.isPassive = true;
self.enableIntegrityCheck = true;
self.enableDiagnostics = true;
self.enableFetchDiagnostics = true;
self.importScripts('_content/Bit.Bswup/bit-bswup.sw.js');The most important line is the last one - the only mandatory config in this file:
self.importScripts('_content/Bit.Bswup/bit-bswup.sw.js');
Unlike the assets in service-worker-assets.js (which Bswup verifies with Subresource
Integrity), the service worker script itself cannot be integrity-pinned: browsers support neither an
integrity option on register() nor SRI for importScripts().
A tampered service-worker.js or bit-bswup.sw.js is effectively persistent,
fully-privileged XSS. Serve both over HTTPS from an origin you control and apply a strict
Content-Security-Policy.
Bswup registers with updateViaCache: 'none' so update checks bypass the HTTP cache for
the whole service-worker.js → bit-bswup.sw.js → service-worker-assets.js
import chain. As defense-in-depth (support is uneven on older Safari/iOS, and proxies are not bound
by it), also send Cache-Control: no-cache for these two files so every fetch
revalidates against the origin.
How the URL-matching lists are matched
assetsInclude, assetsExclude, prohibitedUrls,
serverHandledUrls and serverRenderedUrls all accept the same two kinds of entry:
- a
RegExp(e.g./\/admin\//) is used as the pattern it is - what you want for anything non-trivial; - a string (e.g.
'/admin/') is matched literally as a substring of the URL. It is regex-escaped, so'v1.0'matches onlyv1.0and neverv1X0.
'app.css' matches /css/app.css anywhere in the URL; anchor with a
RegExp such as /\/app\.css$/ if that is too broad. Prefer a RegExp
whenever you need anchoring, alternation or wildcards. Also note: before v-10-6-0 string entries were
silently ignored - see the migration guide.
Asset selection
assetsInclude
The list of file names from the assets list to include when Bswup stores them in cache storage (regex supported).
assetsExclude
The list of file names from the assets list to exclude when Bswup stores them in cache storage (regex supported).
ignoreDefaultInclude / ignoreDefaultExclude
Ignore the default include / exclude arrays Bswup provides. The defaults are:
[/\.dll$/, /\.wasm/, /\.pdb/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/,
/\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/, /\.svg$/, /\.woff2$/, /\.ttf$/, /\.webp$/]/\.wasm/, /\.pdb/ and /\.html/ are deliberately unanchored
(mirroring the standard Blazor template), so variants such as foo.wasm.br also match.
The default excludes keep the service worker's own scripts out of the cache:
[
/^_content\/Bit\.Bswup\/bit-bswup\.sw\.js$/,
/^_content\/Bit\.Bswup\/bit-bswup\.sw\.min\.js$/,
/^_content\/Bit\.Bswup\/bit-bswup\.sw-cleanup\.js$/,
/^_content\/Bit\.Bswup\/bit-bswup\.sw-cleanup\.min\.js$/,
/^service-worker\.js$/,
]externalAssets
The list of external assets to cache that are not included in the auto-generated assets file. For
example, if you're not using index.html (like _host.cshtml), add
{ "url": "/" }.
self.externalAssets = [
{ "url": "/" }, // the host page itself (e.g. _host.cshtml)
"https://fonts.example.com/app-font.woff2", // bare string shorthand
{ "url": /_framework\/resource-collection\..*\.js/ }, // RegExp for server-generated names
{ "url": "/lib/chart.js", "hash": "sha256-..." } // with SRI hash (cache busting + integrity)
];Accepted entry shapes and behaviors:
- An object with a
url(a concrete string, or aRegExpfor server-generated names unknown ahead of time), a bare string, or a bareRegExp; a single value also works without the array. - An entry may carry a
hash(an SRI digest,sha256-...) that participates in?v=cache busting and - whenenableIntegrityCheckis on - in integrity verification, exactly like a manifest asset. - Entries whose
urlcannot be parsed are skipped with a non-fatalrequesterror instead of breaking the worker. - Cross-origin entries are fetched in CORS mode first; when the host sends no CORS headers, Bswup retries with
no-corsand caches the resulting opaque response so the asset still works offline. This fallback is skipped for integrity-checked assets. Browsers pad opaque responses in quota accounting (Chromium reserves several megabytes per entry), so prefer CORS-enabled hosts when you control them. - Media works too: requests carrying a
Rangeheader are answered with a real206 Partial Contentsliced from the cached full body (Safari refuses media served as200for a ranged request); uncached ranged requests pass through with theirRangeintact, and partial responses are never written to the cache. - Entries cached for
RegExppatterns are kept across updates so the app still boots offline, but only the newest three generations per pattern survive each update.
Navigation & URLs
defaultUrl
The default page URL, served from cache for navigation requests (the SPA fallback). Defaults to
index.html; use / when using _Host.cshtml. The value must match
an entry that actually exists in service-worker-assets.js or externalAssets;
the comparison uses resolved URLs, so equivalent spellings match. When nothing matches,
offline navigation cannot work and Bswup logs a defaultUrl ... matches no asset warning
at startup.
- Navigations whose URL is itself a managed asset are served that asset instead of the default document (changed in v-10-6-0): opening
/manifest.jsondirectly shows that file, while route URLs (/counter, ...) still get the app shell. - If your host answers the shell URL with a redirect (e.g.
/→/index.html, common on Cloudflare Pages and Netlify), Bswup rebuilds that response so offline deep-link navigation keeps working instead of failing with a redirect-mode error.
assetsUrl
The path of the compile-time assets manifest (default file name service-worker-assets.js).
The default is resolved relative to the service worker script's own location - which is also where
Blazor publishes the file - so it works unchanged for apps mounted on a sub-path. Set it explicitly
only when the file lives somewhere else; a leading / makes the path origin-absolute.
prohibitedUrls
URLs that should not be accessed (regex supported). Matching requests are answered by the service
worker with 403 Forbidden for every HTTP method (changed in v-10-6-0 - previously
405).
serverHandledUrls
URLs that skip the service worker offline pipeline entirely and are handled only by the server (regex supported) - e.g. /api, /swagger.
serverRenderedUrls
URLs that should be rendered by the server rather than the client while navigating (regex supported) - e.g. /about.html, /privacy.
caseInsensitiveUrl
Enables case-insensitive URL checking - for asset cache matching and every URL-matching regex
list: when enabled, patterns are compiled with the i flag so e.g.
prohibitedUrls: [/\/admin\//] also blocks /ADMIN/.
noPrerenderQuery
The query string attached to the default document request to disable server prerendering, so an
unwanted prerendered result is not cached - e.g. no-prerender=true.
forcePrerender
Forces prerendering of the default document for every navigation request to ensure the server always has the latest version of the app. Useful for server-rendered apps.
Install behavior & resiliency
isPassive
Enables passive mode: assets are not cached in advance but upon first request. Passive mode does not skip the full download entirely - on a first install, once Blazor has started, the service worker still tops up the cache in the background with every asset not yet fetched, so the app ends up fully offline-capable. What passive mode buys is that the first paint is never blocked behind a full precache. Assets lazily fetched by the app while the top-up runs can be downloaded twice in that window - a bandwidth cost, not a correctness issue.
errorTolerance
Controls how the service worker reacts to asset download / cache failures during install:
| Value | Behavior |
|---|---|
lax (default) |
Best-effort install. Asset failures never fail the install; missing assets are filled in
lazily on first fetch. Failures are reported through the error event with
fatal: false and still count toward progress so the bar reaches 100%.
Tolerates optional externalAssets that may legitimately 404, and avoids
leaving a first visit with no service worker to complete the startup handshake. The
download runs under the install event's waitUntil, so
updateReady is only announced once the background fill has settled.
|
strict |
Mirrors the standard Microsoft template / Workbox behavior. If any required asset fails,
the install rejects, the partial cache is discarded, and the previous service worker (if
any) keeps serving. Failed assets are not counted toward progress, so 100% means
every asset succeeded; the abort is reported with reason: 'install-aborted'
and fatal: true. On a first install (no previous version to fall back to)
Bswup starts the app without a service worker so it still boots, and the install is
retried on the next load.
|
maxRetries / retryDelay
maxRetries (default 2) is the number of additional download attempts
after the first when an asset fails transiently during install (a rejected fetch, or HTTP 408/429/5xx).
Deterministic failures - 404/403 and other permanent statuses, and SRI mismatches - are never retried,
since identical bytes would fail identically.
retryDelay (default 300) is the base backoff in milliseconds: attempt
n waits retryDelay * 2^(n-1) plus random jitter, so a mass failure doesn't re-hit
the origin in one synchronized burst.
enableIntegrityCheck
Enables the browsers' built-in integrity verification by setting the integrity attribute
on the requests the service worker creates to fetch assets.
Caching & updates
cacheVersion
Overrides the value used to name the cache bucket (bit-bswup:<scope-path> - <version>).
By default this tracks Blazor's assetsManifest.version (a hash over the published assets),
so the cache rotates automatically whenever any asset hash changes - and only then. Set it to take
manual control:
- Pin it to a stable string so noisy dev rebuilds don't needlessly evict the whole cache.
- Bump it to force a refresh when a meaningful change lives outside Blazor's asset manifest.
- Feed it a build-stamped value (commit SHA, build timestamp) so it bumps automatically per publish.
Only the cache bucket name is affected: per-asset ?v= cache busting and Subresource
Integrity keep using each asset's own hash.
disableHashlessAssetsUpdate
Disables the automatic re-download of hash-less assets (e.g. external assets) that Bswup performs every time an update is found.
enableCacheControl
Adds cache-busting to each asset request (cache: 'no-store' plus a
cache-control: no-cache header). The header is only attached to same-origin requests: it
is not CORS-safelisted, so on a cross-origin asset it would force a preflight most third-party hosts
reject; cross-origin requests rely on the cache: no-store option alone.
Diagnostics
enableDiagnostics: pushes service worker logs to the browser console.enableFetchDiagnostics: additionally logs every fetch event the worker handles.
Modes
A mode is a preset bundle of defaults for the individual settings above
(isPassive, defaultUrl, forcePrerender,
errorTolerance, caseInsensitiveUrl, noPrerenderQuery): it only
fills settings you have not assigned yourself, so any explicit assignment always wins over the preset -
including explicit falsy values such as caseInsensitiveUrl = false.
| Mode | Behavior |
|---|---|
NoPrerender | Disables prerendering of the default document for every navigation request. |
InitialPrerender | Enables prerendering of the default document only for the initial navigation request. |
AlwaysPrerender | Enables prerendering of the default document for every navigation request. |
FullOffline | Full offline mode: all assets are cached and served from cache from the first time the app loads. |