此代码位于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}`);
});
}
}
仍然希望有人可以修复代码并使其防弹,或者干脆声明由于某种原因这在技术上是不可能的。
我找到了一个解决方案,并在几天内确认它有效。它也可以在我加载到 iOS 中的 PWA 上运行。
如果与 wwwroot/service-worker.published.js 中更新的 const CACHE 相结合,我现有的问题函数就可以工作。
我的构建后 Powershell 脚本如下所示:
$currentDate = get-date -format yyyy.MM.dd.HHmm;
# Update service worker
$curDir = Get-Location
$inputFile = $curDir.Path +"\wwwroot\service-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'
我还使用以下构建后 Powershell 脚本来更新 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>(.|\n)*?</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;
我在 Blazor 中使用以下行调用 index.html 中的函数:
await js.InvokeAsync<string>("updateVersion", state.Version);
最后是index.html 中的javascript,它将清除缓存并刷新服务工作线程。
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 中的互操作中调用的函数。
瞧:只需编码。在每个版本中,版本号都会更新。如果用户打开过时的生产代码,页面将自动重新加载,然后运行最新的代码。
嘿,这对你有用,尝试一次
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