The Wayback Machine - https://web.archive.org/web/20211231152151/https://github.com/dotnet/aspnetcore/issues/39252
Skip to content
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

Blazor WASM PWA integrity errors after upgrading from .NET Core 3.1 to .NET 6. #39252

Open
acamlibe opened this issue Dec 31, 2021 · 0 comments
Open

Comments

@acamlibe
Copy link

@acamlibe acamlibe commented Dec 31, 2021

Hi, I have a PWA application that I have developed internally for my company. I recently upgraded it to .NET 6 by creating a new project and moving everything over.

When I went to deploy this last week, everything went wrong. I was getting integrity errors everywhere, and some of the users I had testing for me also had the same issues. The app was able to update its service worker assets when you reloaded with a clear cache, but doing a reload right after would bring the version back to the old one, and eventually just broke the application. I had to revert back to the .NET Core 3.1 version temporarily.

The way I have my PWA setup, it should show an "Update Now" button when I do publish a new version. Normally it's instant, and has worked really well on .NET Core 3.1, but for some reason, it did not show up that time.

I haven't tried since, but what I did was run a PowerShell script to check the hashes found in the service-worker-assets.js file with the calculated hashes, and everything matched for all the files in that failed deployment. I also looked at the blazor.boot.json and the hashes seemed to match there as well.

I can't really tell what happened. I heard that one way to fix this was to delete the obj and bin folders before publishing, but I haven't tried that yet. I don't want to publish until I know for sure what went wrong that day.

And just for more information, here's my deployment process:

  1. Publish to folder output
  2. Move files over to our two web servers (load balanced), and restart the app pool on IIS.
  3. The expected outcome here would be that the next time the user reloads or opens the app, they would get an "Update Now" button at the bottom of their page. This did not happen though.

And just FYI, I use the default web.config that comes with the publish step. I haven't messed around with configuring it.

Any ideas how I can better assess what went wrong here? I believe the browser was holding onto old cache somehow?

Here's the service.worker.published.js file:

self.importScripts('./service-worker-assets.js');
self.addEventListener('install', event => event.waitUntil(onInstall(event)));
self.addEventListener('activate', event => event.waitUntil(onActivate(event)));
self.addEventListener('fetch', event => event.respondWith(onFetch(event)));

const cacheNamePrefix = 'offline-cache-';
const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
const offlineAssetsInclude = [/\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/];
const offlineAssetsExclude = [/^service-worker\.js$/];

const notifyNewVersion = () => {
    const bc = new BroadcastChannel('blazor-channel');

    bc.postMessage('new-version-found');

    bc.onmessage = function (message) {
        if (message && message.data == "skip-waiting") {
            self.skipWaiting();
            bc.postMessage("reload-page");
        }
    }
}

async function onInstall(event) {
    console.info('Service worker: Install');

    // Fetch and cache all matching items from the assets manifest
    const assetsRequests = self.assetsManifest.assets
        .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
        .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
        .map(asset => new Request(asset.url, { integrity: asset.hash }));
    await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));

    notifyNewVersion();
}

async function onActivate(event) {
    console.info('Service worker: Activate');

    // Delete unused caches
    const cacheKeys = await caches.keys();
    await Promise.all(cacheKeys
        .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName)
        .map(key => caches.delete(key)));
}

async function onFetch(event) {
    let cachedResponse = null;
    if (event.request.method === 'GET') {
        // For all navigation requests, try to serve index.html from cache
        // If you need some URLs to be server-rendered, edit the following check to exclude those URLs
        const shouldServeIndexHtml = event.request.mode === 'navigate';

        const request = shouldServeIndexHtml ? 'index.html' : event.request;
        const cache = await caches.open(cacheName);
        cachedResponse = await cache.match(request);
    }

    return cachedResponse || fetch(event.request);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant