-
-
Notifications
You must be signed in to change notification settings - Fork 264
Apply Bswup improvements (#12408) #12418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
msynk
wants to merge
59
commits into
bitfoundation:develop
Choose a base branch
from
msynk:12408-bswup-improvements
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
59 commits
Select commit
Hold shift + click to select a range
825d8af
apply Bswup improvements #12408
msynk c646784
further improvements
msynk 733a05a
resolve review comments
msynk de9c330
resolve review comments II
msynk 23b29b3
resolve review comments III
msynk 088c6d1
resolve review comments IV
msynk c161919
Merge branch 'develop' into 12408-bswup-improvements
msynk 8c11506
resovle review comments V
msynk ea3d330
resolve review comments VI
msynk a71d04f
remove json serializer
msynk ddd6829
fix progress component
msynk 9d73fbf
resolve local review findimgs
msynk 6c96a71
Merge branch '12408-bswup-improvements' of https://github.com/msynk/b…
msynk ce3cd61
Merge branch 'develop' into 12408-bswup-improvements
msynk 5377236
resolve review comments V
msynk a450c91
Merge branch 'develop' into 12408-bswup-improvements
msynk d6f1bd1
resolve review comments VI
msynk bd800d8
resolve review comments VII
msynk 3623e25
Merge branch 'develop' into 12408-bswup-improvements
msynk 754eb63
resolve review comments VIII
msynk 70d385e
fix build issues
msynk a1ee5c5
resolve review comments IX
msynk f92cdaa
resolve review comments X
msynk 20addce
resolve review comments XI
msynk 73401e9
fix variable definition issue
msynk 7721833
restructure demo projects
msynk 3e6197a
improve FullDemo
msynk 021176a
Merge branch 'develop' into 12408-bswup-improvements
msynk 571f537
resolve review comments XII
msynk 968fc99
resolve review comments XIII
msynk 4a55113
Merge branch 'develop' into 12408-bswup-improvements
msynk 3431b3c
add regex support for asset urls
msynk dea4803
Merge branch 'develop' into 12408-bswup-improvements
msynk 4bd6741
fix local findings
msynk 11c8887
add tests
msynk 49b8e8e
add fetch resiliency
msynk e07870b
resolve local review findings
msynk 4ee615c
resolve local review findings II
msynk 6dd9fb9
resolve local findings in loop
msynk ae73eb8
resolve local loop findings
msynk 3ddd5a1
fix FullDemo app
msynk 3a63009
merge demo projects
msynk 075c94d
rename BasicDemo
msynk 0cc0a2b
add document website project
msynk 6c294e8
add
msynk c04b464
fix version badge
msynk dc36feb
fix port numbers
msynk e503f15
Merge branch 'develop' of https://github.com/bitfoundation/bitplatfor…
msynk 7bcb248
resolve review comments 15
msynk f718b2c
resolve review comments
msynk 73ecd0d
resolve review comments 17
msynk b7269d0
resolve review comments 18
msynk a41f645
resolve review comments 19
msynk 8e970da
resolve review comments 20
msynk 03525eb
resolve review comments 21
msynk d8e7aa8
resolve review comments 22
msynk 66a374c
resolve review comments 23
msynk f39a481
resolve review comments 24
msynk 8953762
resolve review comments 25
msynk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,16 @@ | ||
| <LayoutView> | ||
| <Router AppAssembly="@typeof(App).Assembly"> | ||
| <Found Context="routeData"> | ||
| <RouteView RouteData="@routeData" /> | ||
| </Found> | ||
| <NotFound> | ||
| <PageTitle>Not found</PageTitle> | ||
| <p role="alert">Sorry, there's nothing at this address.</p> | ||
| </NotFound> | ||
| </Router> | ||
| </LayoutView> | ||
| <Router AppAssembly="@typeof(App).Assembly"> | ||
| <Found Context="routeData"> | ||
| <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> | ||
| <FocusOnNavigate RouteData="@routeData" Selector="h1" /> | ||
| </Found> | ||
| <NotFound> | ||
| <LayoutView Layout="@typeof(MainLayout)"> | ||
| <PageTitle>Not found - bit Bswup</PageTitle> | ||
| <div class="docs-not-found"> | ||
| <h1>404</h1> | ||
| <p role="alert">Sorry, there's nothing at this address.</p> | ||
| <a class="button-primary" href="/">Back to the docs</a> | ||
| </div> | ||
| </LayoutView> | ||
| </NotFound> | ||
| </Router> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| @page "/cleanup" | ||
|
|
||
| <PageTitle>Backing Out of Bswup - bit Bswup</PageTitle> | ||
|
|
||
| <h1>Backing Out of Bswup</h1> | ||
| <p class="docs-lead"> | ||
| Fully remove Bswup from a deployed app - dropping offline support, or recovering clients stuck on a | ||
| broken worker or cache - with the self-destructing cleanup worker. | ||
| </p> | ||
|
|
||
| <p> | ||
| Replace the <em>content</em> of your <code>service-worker.js</code> <strong>and</strong> | ||
| <code>service-worker.published.js</code> (the file deployed builds actually ship, via the | ||
| <code>ServiceWorker</code> item's <code>PublishedContent</code> mapping) with: | ||
| </p> | ||
| <CodeBlock Language="javascript" Code="self.importScripts('_content/Bit.Bswup/bit-bswup.sw-cleanup.js');" /> | ||
|
|
||
| <h2>What happens next</h2> | ||
| <p>On its next update check, every client installs this self-destructing worker instead. It:</p> | ||
| <ol> | ||
| <li>activates immediately,</li> | ||
| <li>purges this app's Bswup and Blazor caches,</li> | ||
| <li>unregisters its own registration, and</li> | ||
| <li>signals open tabs to detach.</li> | ||
| </ol> | ||
| <p> | ||
| Tabs the previous worker controlled reload once; everything afterwards runs purely from the network, | ||
| even while the page keeps referencing <code>bit-bswup.js</code> - each later load just repeats the | ||
| register/self-unregister cycle silently, with no reloads. | ||
| </p> | ||
| <Callout Type="note" Title="When can the script tag go?"> | ||
| Once no client has loaded the old app for as long as your cache headers require, the | ||
| <code>bit-bswup.js</code> script tag can be removed from the host document too. | ||
| </Callout> | ||
|
|
||
| <h2>Client-side reset without backing out</h2> | ||
| <p> | ||
| If you only need to recover a <em>single</em> broken client (not remove Bswup from the deployment), | ||
| prefer <a href="javascript-api#forcerefresh"><code>BitBswup.forceRefresh()</code></a> - it clears this | ||
| app's caches, unregisters its worker, and reloads, without touching the deployed service worker file. | ||
| </p> | ||
|
|
||
| <div class="pager"> | ||
| <a href="playground"> | ||
| <span class="pager-label">Previous</span> | ||
| <b>← Live Playground</b> | ||
| </a> | ||
| <a class="pager-next" href="migration"> | ||
| <span class="pager-label">Next</span> | ||
| <b>Migrating to 10-6-0 →</b> | ||
| </a> | ||
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,220 @@ | ||
| @page "/events" | ||
|
|
||
| <PageTitle>Events & Handler - bit Bswup</PageTitle> | ||
|
|
||
| <h1>Events & Handler</h1> | ||
| <p class="docs-lead"> | ||
| Bswup reports its whole lifecycle through a single global handler function. Use the built-in | ||
| <a href="progress-ui">progress UI</a>, or write your own handler and drive any markup you like. | ||
| </p> | ||
|
|
||
| <p> | ||
| The handler's name is configured through the <a href="script-options#handler"><code>handler</code></a> | ||
| script attribute (default <code>bitBswupHandler</code>). It receives <code>(type, data)</code> where | ||
| <code>type</code> is one of the <code>BswupMessage</code> constants: | ||
| </p> | ||
|
|
||
| <h2>Event catalog</h2> | ||
| <div class="docs-table-wrapper"> | ||
| <table> | ||
| <thead> | ||
| <tr><th>BswupMessage</th><th>Value</th><th>Raised when</th></tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr><td><code>updateFound</code></td><td><code>UPDATE_FOUND</code></td><td>The browser found a new service worker version and started installing it.</td></tr> | ||
| <tr><td><code>stateChanged</code></td><td><code>STATE_CHANGED</code></td><td>The installing worker's lifecycle state changed (<code>data.currentTarget.state</code>).</td></tr> | ||
| <tr><td><code>downloadStarted</code></td><td><code>DOWNLOAD_STARTED</code></td><td>Asset download began. <code>data.version</code>, <code>data.firstInstall</code>.</td></tr> | ||
| <tr><td><code>downloadProgress</code></td><td><code>DOWNLOAD_PROGRESS</code></td><td>An asset finished. <code>data.percent</code> (0-100), <code>data.index</code> (1-based count), <code>data.asset</code> (<code>url</code>, <code>reqUrl</code>, <code>hash</code>).</td></tr> | ||
| <tr><td><code>downloadFinished</code></td><td><code>DOWNLOAD_FINISHED</code></td><td>All assets are staged. <code>data.firstInstall</code>, <code>data.reload()</code>, <code>data.cleanup()</code>.</td></tr> | ||
| <tr><td><code>updateReady</code></td><td><code>UPDATE_READY</code></td><td>A fully staged update is waiting to be activated (<code>data.reload()</code>).</td></tr> | ||
| <tr><td><code>activate</code></td><td><code>ACTIVATE</code></td><td>A new version activated (<code>data.version</code>).</td></tr> | ||
| <tr><td><code>updateNotFound</code></td><td><code>UPDATE_NOT_FOUND</code></td><td>An update check completed and the app is already on the latest version.</td></tr> | ||
| <tr><td><code>updateCheckFailed</code></td><td><code>UPDATE_CHECK_FAILED</code></td><td>An update check itself failed transiently (offline, server hiccup). Non-blocking - the app keeps running.</td></tr> | ||
| <tr><td><code>error</code></td><td><code>ERROR</code></td><td>A structured install failure - see <a href="#error-payload">below</a>.</td></tr> | ||
| </tbody> | ||
| </table> | ||
| </div> | ||
|
|
||
| <h2>A complete handler</h2> | ||
| <CodeBlock Language="javascript" Code="@HandlerCode" /> | ||
|
|
||
| <h2 id="download-finished">Finishing a download: <code>reload</code> and <code>cleanup</code></h2> | ||
| <ul> | ||
| <li> | ||
| <code>data.reload()</code> activates the staged version. On a <strong>first install</strong> it | ||
| claims the clients and starts Blazor <em>with no reload</em>; on an <strong>update</strong> it | ||
| performs <code>SKIP_WAITING</code> and reloads. | ||
| </li> | ||
| <li> | ||
| <code>data.cleanup()</code> (optional) asks the active service worker to prune this app's stale | ||
| cache buckets right away. It is safe to call at any time - the worker declines while an update is | ||
| staged or staging (pruning then happens automatically on activation), and it never touches another | ||
| app's caches. Most apps never need it: the same pruning already runs on activation and after every | ||
| accepted update. | ||
| </li> | ||
| </ul> | ||
|
|
||
| <Callout Type="warning" Title="Breaking change: updates no longer auto-reload by default"> | ||
| Since v-10-6-0, the built-in <code>BswupProgress</code> component's <code>AutoReload</code> parameter | ||
| defaults to <code>false</code>: when an update finishes downloading, the reload button is shown and the | ||
| new version activates when the user accepts it - an unprompted reload discards whatever in-page state | ||
| the user has mid-session. Set <code>AutoReload="true"</code> to restore the old behavior. First | ||
| installs are unaffected: they always complete the seamless claim-and-start flow (no reload). | ||
| </Callout> | ||
|
|
||
| <h2>Multi-tab updates</h2> | ||
| <p> | ||
| Service workers are single-instance per origin, so accepting an update in one tab activates the new | ||
| version for every open tab. When that happens, Bswup has the new worker claim all clients and each | ||
| <em>other</em> tab reloads itself automatically (via <code>controllerchange</code>) onto the new | ||
| version. This keeps every tab consistent and avoids the classic failure where an old tab keeps running | ||
| old app code while its asset requests are served from the new version's cache (mismatched boot config / | ||
| DLL hashes). The first install is exempt: claiming a client for the first time starts Blazor and does | ||
| not trigger a reload. | ||
| </p> | ||
|
|
||
| <h2 id="error-payload">The <code>error</code> payload</h2> | ||
| <p>Install failures are structured:</p> | ||
| <div class="docs-table-wrapper"> | ||
| <table> | ||
| <thead> | ||
| <tr><th>Field</th><th>Meaning</th></tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <td><code>reason</code></td> | ||
| <td> | ||
| One of <code>manifest</code>, <code>integrity</code>, <code>fetch</code>, | ||
| <code>cache</code>, <code>request</code>, <code>install-incomplete</code>, | ||
| <code>install-aborted</code>, or <code>install-infra</code> (the install died | ||
| before/while touching CacheStorage - storage pressure, a broken private mode - always | ||
| fatal). | ||
| </td> | ||
| </tr> | ||
|
msynk marked this conversation as resolved.
|
||
| <tr><td><code>message</code></td><td>Human-readable description.</td></tr> | ||
| <tr><td><code>url</code> / <code>hash</code></td><td>The offending asset, when known.</td></tr> | ||
| <tr> | ||
| <td><code>fatal</code></td> | ||
| <td> | ||
| Whether the install actually stopped. Under the default <code>lax</code> tolerance a | ||
| failed asset is reported with <code>fatal: false</code> - the install still succeeds and | ||
| the asset is fetched from the network on first use - so treat it as a warning, not a | ||
| dead app. <code>fatal: true</code> means no usable staged version is available to this | ||
| page - though a worker may still have been installed (a lax | ||
| <code>install-infra</code> failure resolves the install so the worker can keep serving | ||
| as a network pass-through). | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td><code>firstInstall</code></td> | ||
| <td> | ||
| Where a fatal failure landed. <code>true</code>: before the app ever booted - Bswup | ||
| starts the app without a service worker so it still boots. <code>false</code>: a | ||
| background <em>update</em> failed - the app keeps running on the current version (the | ||
| previous worker keeps serving). | ||
| </td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
| </div> | ||
| <CodeBlock Language="javascript" Code="@ErrorHandlerCode" /> | ||
|
|
||
| <div class="pager"> | ||
| <a href="service-worker"> | ||
| <span class="pager-label">Previous</span> | ||
| <b>← Service Worker Settings</b> | ||
| </a> | ||
| <a class="pager-next" href="progress-ui"> | ||
| <span class="pager-label">Next</span> | ||
| <b>Progress UI →</b> | ||
| </a> | ||
| </div> | ||
|
|
||
| @code { | ||
| private const string HandlerCode = @"const appEl = document.getElementById('app'); | ||
| const bswupEl = document.getElementById('bit-bswup'); | ||
| const progressBar = document.getElementById('bit-bswup-progress-bar'); | ||
| const reloadButton = document.getElementById('bit-bswup-reload'); | ||
|
|
||
| function bitBswupHandler(type, data) { | ||
| switch (type) { | ||
| case BswupMessage.updateFound: return console.log('an update found.'); | ||
|
|
||
| case BswupMessage.stateChanged: return console.log('state:', data.currentTarget.state); | ||
|
|
||
| case BswupMessage.activate: return console.log('new version activated:', data.version); | ||
|
|
||
| case BswupMessage.downloadStarted: | ||
| // A background update downloads behind the running app - only a first | ||
| // install owns the screen (firstInstall rides on every message). | ||
| if (data?.firstInstall === false) return; | ||
| appEl.style.display = 'none'; | ||
| bswupEl.style.display = 'block'; | ||
| return console.log('downloading assets started:', data?.version); | ||
|
|
||
| case BswupMessage.downloadProgress: | ||
| progressBar.style.width = `${Math.round(data.percent)}%`; | ||
| return console.log('asset downloaded:', data.asset.url, data); | ||
|
|
||
| case BswupMessage.downloadFinished: | ||
| if (data.firstInstall) { | ||
| // First install: claim + start Blazor, no page reload. Reveal the app even if | ||
| // the claim/start stalls or rejects - a hidden #app with no way out is worse | ||
| // than an app shown behind a stale splash. | ||
| const reveal = () => { | ||
| appEl.style.display = 'block'; | ||
| bswupEl.style.display = 'none'; | ||
| }; | ||
| const failSafe = setTimeout(reveal, 10000); | ||
| data.reload() | ||
| .catch(err => console.error('Bswup first install failed to start:', err)) | ||
| .then(() => { clearTimeout(failSafe); reveal(); }); | ||
| } else { | ||
| // Update: let the user accept it. | ||
| reloadButton.style.display = 'block'; | ||
| reloadButton.onclick = data.reload; | ||
| } | ||
| return console.log('downloading assets finished.'); | ||
|
|
||
| case BswupMessage.updateReady: | ||
| reloadButton.style.display = 'block'; | ||
| reloadButton.onclick = data.reload; | ||
| return console.log('new update ready.'); | ||
|
|
||
| case BswupMessage.updateNotFound: | ||
| return console.log('already on the latest version.'); | ||
|
|
||
| case BswupMessage.updateCheckFailed: | ||
| return console.warn('could not check for updates right now:', data); | ||
|
|
||
| case BswupMessage.error: | ||
| if (data.fatal === false) { | ||
| // lax tolerance: the install continued; the asset lazy-fills later. | ||
| return console.warn('Bswup asset skipped:', data.reason, data.message); | ||
| } | ||
| console.error('Bswup install error:', data.reason, data.message, data); | ||
| if (data.firstInstall) { | ||
| // Fatal first-install failure: Bswup force-starts Blazor from the network; | ||
| // reveal the app instead of leaving it booted behind the splash. | ||
| appEl.style.display = 'block'; | ||
| bswupEl.style.display = 'none'; | ||
| } | ||
| return; | ||
| } | ||
| }"; | ||
|
|
||
| private const string ErrorHandlerCode = @"case BswupMessage.error: | ||
| if (data.fatal === false) { | ||
| console.warn('Bswup asset skipped:', data.reason, data.message, data); | ||
| return; | ||
| } | ||
| if (data.firstInstall === false) { | ||
| // A background update failed - the running app is untouched. | ||
| return; | ||
| } | ||
| // Fatal first-install failure: Bswup force-starts Blazor from the network; | ||
| // reveal the app instead of leaving it booted behind the splash. | ||
| appEl.style.display = 'block'; | ||
| bswupEl.style.display = 'none'; | ||
| return;"; | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.