Migrating to v-10-6-0
v-10-6-0 is a resilience-focused release. Most changes are internal hardening; this page lists what is visible when upgrading.
Action items
1. Updates no longer auto-reload. BswupProgress.AutoReload now defaults to false - updates announce themselves through the reload button. Set AutoReload="true" to restore the old behavior.
2. Blocked URLs answer 403. prohibitedUrls matches are answered with 403 Forbidden (previously 405). Code detecting a blocked URL by status must check for 403.
3. String entries now take effect. Strings in the URL-matching lists (assetsInclude, assetsExclude, prohibitedUrls, serverHandledUrls, serverRenderedUrls) are now matched literally as substrings. Previous releases silently ignored them - audit any strings sitting in those lists, because they take effect for the first time after upgrading.
4. Hand-written splash markup needs one edit. Move <button id="bit-bswup-reload"> outside the #bit-bswup overlay (and give it a z-index), optionally adding a visually-hidden <span id="bit-bswup-reload-status" role="status"> next to it. The built-in handling no longer reveals the overlay for updates, so a button left inside it would never become visible. The BswupProgress component ships this layout already.
Behavior changes
- Cache buckets are scope-qualified:
bit-bswup:<scope-path> - <version>(previouslybit-bswup - <version>). Multiple Bswup apps on one origin no longer evict each other's caches; the migration from legacy-named buckets is automatic and does not re-download. - Under the default
laxtolerance, the asset download now runs inside the install event (waitUntil): the browser keeps the worker alive for the whole download, andupdateReadyis only raised once the new version is fully staged - previously it could fire while the download had barely started. assetsUrldefaults to a path resolved against the service worker script's own location (previously root-absolute), so apps mounted on a sub-path work without configuration.- The
cleanupcallback only prunes when no update is staged or staging, andBitBswup.forceRefresh()'s default filter clears only this app's own, legacy, and Blazor caches. The same staged-or-staging guard protects every cache-pruning path, so a prune can never race a newer install's freshly written bucket. - Requests carrying a
Rangeheader are answered with real206 Partial Contentslices from cached bodies (cached media now plays in Safari), and partial responses are never written to the cache. - Updates found later in the same session as the first install are treated as real updates:
updateReadyis raised,downloadFinishedcarriesfirstInstall: false, and accepting them runs the normalSKIP_WAITINGflow. Previously a long-lived tab kept classifying every later update as another first install. - Navigations whose URL is itself a managed asset (e.g. opening
/manifest.jsondirectly) are served that asset instead of the SPA default document. - An update's re-download of the default document and of hash-less assets no longer deletes the existing cache entry first: if the refresh fails (offline mid-update), the previous copy keeps serving - including offline navigation.
- The built-in progress UI stays out of the way during background updates: the full-screen splash is first-install only (
downloadStarted/downloadProgresspayloads carryfirstInstallso custom handlers can do the same), the reload button lives outside the overlay, it is announced via arole="status"region, and the overlay no longer swallows clicks outside its content. - A first install completes even when no handler function is registered at all (previously the app waited out the full
stallTimeoutbehind the splash). - The cleanup worker unregisters its own registration during teardown and no longer claims clients; the page reloads on
UNREGISTERonly while actually controlled, removing a reload-loop hazard. - The passive-mode background top-up after first boot is deterministic: it fills every asset still missing from the cache.
- The default asset excludes cover all shipped worker-script variants (
bit-bswup.sw.min.js,bit-bswup.sw-cleanup.js,bit-bswup.sw-cleanup.min.js). - A manifest or
externalAssetsentry whose URL cannot be parsed is skipped with a non-fatalrequesterror instead of killing the whole service worker at startup. - A navigation to a URL that only a
RegExpexternalAssets pattern matches is served the app shell, never the pattern asset - and a shell cache miss during navigation is refilled from the shell's own URL, never from the navigated route's URL. WAITING_SKIPPEDandUNREGISTERnever reload an uncontrolled page anymore; they make sure the app is booted instead. Activating a first install throughBitBswup.skipWaiting()completes the seamless claim-and-start flow instead of reloading.- A page that loads while an update is already mid-install now observes it:
updateReady/stateChangedfire in that tab when the update finishes staging. - An exception thrown by the app's
bitBswupHandlerno longer breaks the update pipeline (it is logged, and the remaining messages still dispatch).
New capabilities
- Update polling: the
updateInterval/updateOnVisibilityscript attributes, a registration-awareBitBswup.checkForUpdate(), and theupdateNotFound/updateCheckFailedevents. - Install robustness:
errorTolerance(lax/strict), transient-failure retries (maxRetries,retryDelay), thestallTimeoutfirst-install watchdog, and structurederrorpayloads (reason,fatal,firstInstall- including the terminalinstall-infrareason). - Storage:
persistStorage/BitBswup.persistStorage()for eviction-resistant storage, andcacheVersionfor manual control of cache-bucket rotation. - Registration: automatic retry with the default scope when the browser rejects the configured
scope, and fingerprint-tolerant Blazor entry-script detection for .NET 9+@Assets[...]references.