Forcing reload of Blazor client after publishing changes

I have a Blazor app that I'm deploying to Azure for some alpha testing. I've managed to do this and I can run the app from the website just fine.

The problem comes when I make changes to the client and server projects and republish them. Whatever browser is running the client will run whatever is already in the browser cache until the browser history is cleared. That means until the history is cleared the app appears broken because the client requests on the old version don't match the new server API - not to mention my client side changes don't get tested.

How can I force a reload of the client when I publish my changes? Do I have to tell the browser not to cache my app (not sure how on blazor) and take the performance hit until my app stabilizes? Or is there a way to force a client reload after the first API call using some middleware or something?

Or am I missing something?

Edit: It may be relevant that I used the PWA template provided in Blazor WebAssembly 3.2.0 Preview 2. I'm still running the app from a browser, but it seems possible that enabling the PWA option changed the behavior of the app even when running it as a regular website.

Upvotes: 24

Views: 19052

Answers (7)

titol
titol

Reputation: 1149

If this is PWA application, you should have service-worker.js file. If you will expand it, you will see service-worker.published.js file.

Open it and find async function onInstall(event) method. Now you should put self.skipWaiting(); just below console.info('Service worker: Install');. It all should look like this:

async function onInstall(event) {
    console.info('Service worker: Install');
    self.skipWaiting();
    //rest of the function code
}

If you are curious what and why, you should read this article, section Update completion after user navigation away from app

For as long as the list of "clients," which are tabs or windows displaying your app, is nonempty, the worker continues waiting. The reason service workers do this is to guarantee consistency. Consistency means that all resources are fetched from the same atomic cache.

Upvotes: 0

szczellak
szczellak

Reputation: 51

If anyone looks solution for Azure Pipelines and Azure Static Web App deployment, here is what worked for me:

  1. Added following line on top of service-worker.published.js file.

const CACHE_VERSION = '{#CACHE_VERSION#}'

  1. Added Bash step to *.yaml file, just change your app location accordingly.
  - master

pool:
  vmImage: ubuntu-latest

steps:
  - checkout: self
    submodules: true
  - bash: 'sed -i ''s/{#CACHE_VERSION#}/$(Build.BuildId)/'' MathApp/wwwroot/service-worker.published.js'
    
  - task: AzureStaticWebApp@0
    inputs:
      app_location: 'MathApp'
      output_location: 'wwwroot'
      azure_static_web_apps_api_token: $(deployment_token)

Upvotes: 5

Kasper Olesen
Kasper Olesen

Reputation: 136

I finally found an answer for this that helped me. If you do not need PWA, you can remove it and Chrome (and probably other browsers) should stop clinging on to an old client even after deleting cache and fully reloading. Because after having done this my Chrome still reloaded it. For my app I do not need to use this caching feature or to be able to install it as an app.

I found the answer here: Blazor Chrome caching issues

How to remove PWA:

  1. Delete the following files from wwwroot:
/wwwroot/manifest.json
/wwwroot/service-worker.js
/wwwroot/service-worker.published.js
  1. Delete this line from /wwwroot/index.html
<script>navigator.serviceWorker.register('service-worker.js');</script>
  1. Delete those lines from your csproj file
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />

Also... to actually get rid of the app in Chrome, because I had already loaded it this way, I installed it as an app and then uninstalled the app and removed it from Chrome. That finally got me out of this whole loop with Chrome keeping the app and refusing to fully update it in the browser cache / memory / wherever it kept the app

Upvotes: -1

Ranvir
Ranvir

Reputation: 2142

This is an extension to the above solution if you are working with Github actions.

Add following step in .github\workflows\whatever-file-name-you-have.yml

- name: UpdateVersion
    uses: datamonsters/replace-action@v2
    id: sub
    with:enter code here
      files: 'Your.App/wwwroot/service-worker.published.js'
      replacements: '%%CACHE_VERSION%%=${{ github.run_id }}'

I have used {{ github.run_id }} to get a unique-ish value, but you could opt for any other random string either from https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context or bring your own version.

And the main solution lies in editing service-worker.published.js

const CACHE_VERSION = '%%CACHE_VERSION%%'
const cacheName = `${cacheNamePrefix}${CACHE_VERSION}`;

Upvotes: 2

Chris Berlin
Chris Berlin

Reputation: 1067

This answer is intended to complement Ryan Hill's answer:

Blazor automatically updates to the newer version (at least in .NET 5, possibly earlier too). This happens when the application is first closed and restarted in ALL browser tabs including the installed app (which is another browser tab).

The following article helped me a lot:
https://learn.microsoft.com/en-us/aspnet/core/blazor/progressive-web-app?view=aspnetcore-5.0&tabs=visual-studio#installation-and-app-manifest-1

Also helpful: https://www.eugenechiang.com/2021/05/22/forcing-reload-of-blazor-client-after-publishing-changes/

Upvotes: 1

Sarang Kulkarni
Sarang Kulkarni

Reputation: 367

if you are working on dot net core3.X PWA app, you can add comment in service-worker.published.js so that when browser will compare its cached service worker with updated one, browser will track the changes and load new one.

Upvotes: 4

Ryan Hill
Ryan Hill

Reputation: 1942

Since your app is a PWA, you can declare a js file for registration in the navigator.serviceWorker object. This my.js file can contain a const CACHE_VERSION = 1.0. Updating this value should force the client to download the latest files. See Jeremy Likness' blog post for more info.

Upvotes: 16

Related Questions