【问题标题】:Force a total refresh of Blazor WebAssembly PWA app from Javascript从 Javascript 强制完全刷新 Blazor WebAssembly PWA 应用程序
【发布时间】:2022-12-12 18:05:58
【问题描述】:

此代码位于 index.html 中。我用我的最新版本的 Blazor WebAssembly PWA 应用程序调用 updateVersion。第一行是 Service Worker 的原始注册,它是 Blazor 应用程序模板的一部分。剩下的都是我加的。

navigator.serviceWorker.register('service-worker.js');

function updateVersion(newVersion) {
    var key = 'x-photish-version';

    var oldVersion = localStorage.getItem(key);

    if (oldVersion == null) {
        localStorage.setItem(key, newVersion);
    }
    else if (newVersion != oldVersion) {
        localStorage.setItem(key, newVersion);

        // Reload service worker
        navigator.serviceWorker.register('service-worker.js').then(function (registration) {

            caches.delete("blazor-resources-/").then(function (e) {
                console.log("'blazor-resources-/' cache deleted");
            });

            registration.update();

            window.location.reload(); 
        }).catch(function (error) {
            // registration failed
            console.log(`Registration failed with ${error}`);
        });
    }
}

版本部分有效。它检测到该版本是新版本,并正确输入代码的 newVersion != oldVersion 部分,我想在其中确保应用程序已完全刷新。

为了测试它,我发布了我的应用程序的新版本,对我的应用程序进行了一些微不足道的更改,它检测到它是一个新版本并重新加载页面。而且我的小应用程序更改没有出现。它显示了旧版本的应用程序。

我必须从代​​码中找到一种方法来执行此操作,因为我不希望用户在每次加载页面时都检索到最新内容。仅当我实际部署了新版本的代码时。

我该怎么做才能确保刷新 serviceworker 并且不缓存 blazor 应用程序本身的缓存?

更新: 我认为将代码更改为以下内容后问题已解决,但我仍然看到某些情况下它不起作用。

navigator.serviceWorker.register('service-worker.js');

function updateVersion(newVersion) {
    var key = 'x-photish-version';

    var oldVersion = localStorage.getItem(key);

    if (oldVersion == null) {
        localStorage.setItem(key, newVersion);
    }
    else if (newVersion != oldVersion) {
        localStorage.setItem(key, newVersion);

        caches.delete("blazor-resources-/").then(function (e) {
            console.log("'blazor-resources-/' cache deleted");
        });

        // Reload service worker
        navigator.serviceWorker.register('/service-worker.js', { updateViaCache: 'none' }).then(function (registration) {

            window.location.reload(); 

        }).catch(function (error) {
            // registration failed
            console.log(`Registration failed with ${error}`);
        });
    }
}

仍然希望有人可以修复代码并使其无懈可击,或者干脆声明由​​于某种原因这在技术上是不可能的。

【问题讨论】:

  • 我尝试在下面给出一个很好的解决方案,请检查一次

标签: blazor progressive-web-apps service-worker blazor-webassembly


【解决方案1】:

我找到了一个解决方案,并在几天内确认它有效。它也适用于加载到 iOS 中的我的 PWA。

如果与 wwwroot/ 中更新的 const CACHE 结合使用,我现有的问题功能将起作用service-worker.published.js.

我的构建后电源外壳脚本如下所示:

$currentDate = get-date -format yyyy.MM.dd.HHmm;

# Update service worker
$curDir = Get-Location
$inputFile = $curDir.Path +"wwwrootservice-worker.published.js"
$findString = "const CACHE_VERSION =.+"
$replaceString = "const CACHE_VERSION = '$currentDate'"
(Get-Content $inputFile) | ForEach-Object { $_ -replace $findString , $replaceString } | Set-Content $inputFile

Write-Host "Service Worker Updated:     $currentDate"

为了让它工作,我必须手动将这一行添加到service-worker.published.js:

const CACHE_VERSION = '2022.08.10.2222'

我也在使用以下后期构建电源外壳用于更新 version.txt 中的版本的脚本,我一直都知道它会被更新。然后我还更新了 csproj 中的程序集版本。这样我就可以比较这两个值,看看我是否真的在运行最新的代码:

param([string]$ProjectDir, [string]$ProjectPath);

$currentDate = get-date -format yyyy.MM.dd.HHmm;

# Update version.txt
$versionFilePath = $ProjectDir + "/wwwroot/version.txt"
Set-Content -Path $versionFilePath -Value $currentDate -NoNewline

Write-Host "version.txt Updated:        $currentDate"

# Update actual assembly version
$find = "<Version>(.|
)*?</Version>";
$replace = "<Version>" + $currentDate + "</Version>";
$csproj = Get-Content $ProjectPath
$csprojUpdated = $csproj -replace $find, $replace

Set-Content -Path $ProjectPath -Value $csprojUpdated

Write-Host "Assembly Version Updated:   $currentDate"

供您参考,我在中检查了这样的程序集版本C#:

assemblyVersion = Assembly.GetExecutingAssembly()?.
            GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.
            InformationalVersion;

我通过一个简单的 http 调用检查了最新版本,但在C#.

var message = new HttpRequestMessage
{
    Method = HttpMethod.Get,
    RequestUri = new Uri(baseUri + "version.txt?nocache=" + DateTime.Now.ToString("yyyyMMddHHmmss"))
};
message.Headers.CacheControl = new CacheControlHeaderValue
{
    NoCache = true
};

var versionResponse = await http.SendAsync(message);
var version = await versionResponse.Content.ReadAsStringAsync();

return version;

我在 index.html 中使用 Blazor 中的这一行调用我的函数:

await js.InvokeAsync<string>("updateVersion", state.Version);

最后是javascript在 index.html 中,这将清除缓存并刷新 service-worker。

navigator.serviceWorker.register('service-worker.js');

function updateVersion(newVersion) {
    var key = 'x-photish-version';

    var oldVersion = localStorage.getItem(key);

    if (oldVersion == null) {
        localStorage.setItem(key, newVersion);
    }
    else if (newVersion != oldVersion) {
        localStorage.setItem(key, newVersion);

        caches.delete("blazor-resources-/").then(function (e) {
            console.log("'blazor-resources-/' cache deleted");
        });

        // Reload service worker
        navigator.serviceWorker.register('/service-worker.js', { updateViaCache: 'none' }).then(function (registration) {

            window.location.reload(); 

        }).catch(function (error) {
            // registration failed
            console.log(`Registration failed with ${error}`);
        });
    }
}

第一行包含在标准 Blazor 模板中。剩下的是从 Blazor 中的互操作调用的函数。

瞧:只是代码。在每次构建时,版本号都会更新。如果用户打开过时的生产代码,页面将自动重新加载,然后运行最新代码。

【讨论】:

  • 旁注:看起来“caches.delete”部分并不是真正必要的
【解决方案2】:

嘿,这对你有用,试试这个

window.updateAvailable = new Promise((resolve, reject) => {
  if (!('serviceWorker' in navigator)) {
    const errorMessage = `This browser doesn't support service workers`;
    console.error(errorMessage);
    reject(errorMessage);
    return;
  }

  navigator.serviceWorker.register('/service-worker.js')
    .then(registration => {
      console.info(`Service worker registration successful (scope: ${registration.scope})`);

      registration.onupdatefound = () => {
        const installingServiceWorker = registration.installing;
        installingServiceWorker.onstatechange = () => {
          if (installingServiceWorker.state === 'installed') {
            resolve(!!navigator.serviceWorker.controller);
          }
        }
      };
    })
    .catch(error => {
      console.error('Service worker registration failed with error:', error);
      reject(error);
    });
});

window.registerForUpdateAvailableNotification = (caller, methodName) => {
  window.updateAvailable.then(isUpdateAvailable => {
    if (isUpdateAvailable) {
      caller.invokeMethodAsync(methodName).then();
    }
  });
};

也检查参考:https://gist.github.com/huysentruitw/24b23ec49ebd38c9ff891ffb83f06088#file-service-worker-js

【讨论】:

  • 感谢您的贡献。 “onupdatefound”将如何触发?它基于什么?
  • 此外,这看起来像是对 service-worker 的更改。在这种情况下,使用 Blazor,服务工作者是由框架/模板创建的,而不是我直接控制的。
  • 总结:我不明白你回答的上下文。它似乎没有解决问题。但也许我只是不明白把它放在哪里。你可以说得更详细点吗?
  • 是的,给我一些时间
【解决方案3】:

我在这里找到了类似的帖子。希望这个解决方案对你有帮助

https://whuysentruit.medium.com/blazor-wasm-pwa-adding-a-new-update-available-notification-d9f65c4ad13

【讨论】:

猜你喜欢
  • 2021-06-28
  • 1970-01-01
  • 2021-10-29
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 2012-09-04
  • 2021-07-31
  • 2021-10-26
相关资源
最近更新 更多