π₯ Introduction
Please imagine the case that you have a Blazor WebAssembly PWA site that supports offline mode, and you've been opening that PWA by a web browser.
If you published a new version of that PWA, you might want to verify it, I guess. In this case, you will reload the page on that web browser.
However, you might never see the contents of the new version unexpectedly even though you hard-reload it. Disabling cache via the browser's developer tools window or clicking the "Empty cache and hard refresh" menu item from right-clicking the browser's reload icon button doesn't have any effect at all.π±
To enable the new version of that PWA, you must close the browser's "all" tabs that is opening that PWA site once. After closing them once and reopening that PWA site, you will see the contents of the new version of that PWA.
π€ This behavior is "by design"
This is by design come from web browser's specifications and from the default implementation of the service worker JavaScript that is generated by the project template of Visual Studio or .NET SDK.
First of I should explain is a service worker will be updated to a new one "atomically". When a web browser detects a new version of service worker JavaScript code, a web browser will load it but makes it remain in the "waiting to activate" status. This is a standard web platform behavior. A service worker is a process shared by all browser tabs and control caching mechanism offline support. Therefore if its update mechanism is not "atomically", it will cause critical confusion, such as different tabs of the same PWA different behave or the page contents of the current version being partially contaminated by the new versions' contents.
βοΈ Update to the next version without closing all tab
However, in some cases, you might need to make the PWA site able to update to the next version immediately without closing all tabs.
In this case, the better practice is notifying the next version is ready to users via its user interface. And if users respond to that UI to update to the next version, your service worker can be implemented to do that via the skipWaiting()
method.
Unfortunately, the implementation will be complicated a little.
To be able to invoke the
skipWaiting()
method in the service worker process from outside of the service worker process, such as user interaction code, implement service worker JavaScript to handle the specific "message" and call theskipWaiting()
method in that message handler.Implement the user interface that will show a message such as "The next version is ready" and a button such as "Update now". And make that UI send the specific message to the service worker process to invoke the
skipWaiting()
method of the service worker process when users click the button.Handle the promise callback of the
navigator.serviceWorker.register
method.if there is a "waiting" service worker process (that is the new version), then notify the next version is ready to users via UI.
handle the
updatefound
event of the service worker registration object. If theupdatefound
event is fired, handle thestatechange
event of the service worker process.If the
statechange
event of the service worker process is fired, then check the current status of that service worker process. If the status is "installed", then notify the next version is ready to users via UI.If the status is "activated", that means users respond to the UI, and the
skipWaiting()
method in the service worker process is invoked. Therefore reload the current page by calling thewindow.location.reload()
method.
...Please don't misunderstand me, but are you keeping up with this explanation? π
π The "Blazor PWA Updater" NuGet package and component
Fortunately, you don't need to implement all of the code above by yourself. Instead, you can use the "Blazor PWA Updater" NuGet package and its component.
Install the
Toolbelt.Blazor.PWA.Updater
NuGet package.Register a "PWA updater" service to a service provider at startup.
Place a
<PWAUpdater>
component somewhere in your Blazor PWAAdd the
"SKIP_WAITING"
message handler to theservice-worker.published.js
file and invoke theskipWaiting()
in that message handler.Replace the script element
<script>navigator.serviceWorker.register('service-worker.js');</script>
inside of theindex.html
to
<script src="_content/Toolbelt.Blazor.PWA.Updater.Service/script.min.js"></script>
.
That's all. After the implementation above, you will get the ability on your Blazor PWA to update to the new version immediately via user interaction.
You can also customize the appearance of the <PWAUpdater>
, such as notification text, button caption, text color, background color, sizes, and position.
If you don't prefer the appearance and behavior of the <PWAUpdater>
at all, you can also implement the user interface from scratch with minimal effort.
The IPWAUpdaterService
service lived in the Toolbelt.Blazor.PWA.Updater.Service
NuGet package is exposing NextVersionIsWaiting
event and SkipWaitingAsync()
method. So you can build your user interface with this service by yourself.
For more details, please visit the GitHub repository of the "Blazor PWA Updater" and read the README of it.
jsakamoto / Toolbelt.Blazor.PWA.Updater
Provide "Update Now" UI and feature to your Blazor PWA that appears when the next version of one is available.
π Summary
Provide "Update Now" UI and feature to your Blazor PWA that appears when the next version of one is available.
Supported platforms
.NET 6 or later. Both Blazor Server and Blazor Assembly are supported.
π€ Backgrounds
Typically, a service worker of PWA is never updated even when updated contents have been deployed to a server, even if you reload the page of that PWA. After the user has navigated away from the PWA in all tabs, updates will complete. This is not specific to Blazor, but rather is a standard web platform behavior.
For more detail, please see also the following link on the Microsoft Docs site.
"ASP.NET Core Blazor Progressive Web App (PWA)" | Miceooft Docs
However, sometimes, a site owner or a developer may want updates completed as soon as possible. In that case, all we can do is notify the user thatβ¦
β οΈ Notice
Please keep in your mind that kind of these updating notifications sometimes makes users feel annoyed, especially if it happens so often.
If you don't have enough reason to implement such a notification user interface to update the new version immediately, it will be better to keep it by the default implementation.
β€οΈHappy coding :)
Top comments (0)