DEV Community

Cover image for Why can't your Blazor WebAssembly PWA with offline support update even though you reload it?
jsakamoto
jsakamoto

Posted on

Why can't your Blazor WebAssembly PWA with offline support update even though you reload it?

πŸ˜₯ 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.

  1. 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 the skipWaiting() method in that message handler.

  2. 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.

  3. Handle the promise callback of the navigator.serviceWorker.register method.

  4. if there is a "waiting" service worker process (that is the new version), then notify the next version is ready to users via UI.

  5. handle the updatefound event of the service worker registration object. If the updatefound event is fired, handle the statechange event of the service worker process.

  6. 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.

  7. 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 the window.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.

  1. Install the Toolbelt.Blazor.PWA.Updater NuGet package.

  2. Register a "PWA updater" service to a service provider at startup.

  3. Place a <PWAUpdater> component somewhere in your Blazor PWA

  4. Add the "SKIP_WAITING" message handler to the service-worker.published.js file and invoke the skipWaiting() in that message handler.

  5. Replace the script element <script>navigator.serviceWorker.register('service-worker.js');</script> inside of the index.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.

GitHub logo 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.

Blazor PWA Updater NuGet Package

πŸ“ 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)