我有一个Angular PWA。直到我从Angular 5.0升级到7.2之前,它的服务人员都可以正常工作
升级后,我在/ ngsw / state中看到以下错误
驱动程序状态:SAFE_MODE(由于错误而初始化失败:违反不变式(初始化):最新的哈希空值未知) 清单initialize / <@https:// {{domain}} .com / ngsw-worker.js:2227:27 履行@https:// {{domain}} .com / ngsw-worker.js:1772:52)最新 清单杂凑:无最后更新检查:永不
应用背景
检查更新的代码
if (this.updates.isEnabled) {
const appIsStable$ = this.appRef.isStable.pipe(first(isStable => isStable === true));
const every21600Ms$ = interval(6 * 60 * 60);
const every21600MsOnceAppIsStable$ = concat(appIsStable$, every21600Ms$);
// poll the service worker to check for updates
every21600MsOnceAppIsStable$.subscribe(() =>
this.updates.checkForUpdate()
);
}
到目前为止,我的研究和故障排除步骤:
在Chrome中
在Microsoft Edge中
我的想法和期望
答案 0 :(得分:1)
此问题将从Angular 8.2.14版本开始修复。仅较旧版本才需要以下解决方法。
这似乎是Angular服务工作者中的一个众所周知的错误,并且我们可能会在某个时候希望有补丁/工作版本。如issue 25611所述,可以在shobhit vaish中找到大多数信息。
但是,如果您现在正在寻找解决方案,或者您将坚持使用较旧的Angular 7/8版本,而该版本可能不会很快得到修补,那么我将尝试总结当前已知的解决方法。 (而且,它们可能不符合“适当的解决方案”的条件。)
ngsw-worker.js
您可以在ngsw-worker.js
之后修补ng run app:build:production
文件,该文件通常位于项目内的www
文件夹中(如果您未更改Angular {{1} }。或者,您可以在outputPath
内进行构建之前对其进行修补。
取决于您构建应用的频率,您可以简单地手动进行操作(即使用您选择的文本编辑器),也可以例如借助sed编写脚本。
现在您有两个选择:
node_modules/@angular/service-worker
搜索
handleMessage()
并替换为
handleMessage(msg, from) {
return __awaiter$5(this, void 0, void 0, function* () {
根据您的 handleMessage(msg, from) {
return __awaiter$5(this, void 0, void 0, function* () {
if (this.initialized === null) {
this.initialized = this.initialize();
}
try {
yield this.initialized;
}
catch (e) {
this.state = DriverReadyState.SAFE_MODE;
this.stateMessage = `Initialization failed due to handleMessage() error: ${errorToString(e)}`;
}
版本,@angular/service-worker
的签名对您来说可能会有所不同,您可以编写更复杂的handleMessage()
,但希望/可能永远不会达到{{1} }仍然阻止。
此修补程序基本上是a comment by gkalpak中建议的修补程序,官方修补程序很可能也是这样的。
catch
搜索
catch
并替换为
initialize()
这样,您将确保 try {
// Read them from the DB simultaneously.
[manifests, assignments, latest] = yield Promise.all([
table.read('manifests'),
table.read('assignments'),
table.read('latest'),
]);
的{{1}}块将实际运行,并防止服务工作者输入 try {
// Read them from the DB simultaneously.
[manifests, assignments, latest] = yield Promise.all([
table.read('manifests'),
table.read('assignments'),
table.read('latest'),
]);
if (latest.latest === null) throw new Error('Error latest.latest is null for what ever reason...');
。但是,由于此问题,它可能不如第一个补丁那么可靠,但对于已经在catch
中的服务工作者也可以使用。它是在a comment by hsta中提出的。
如果您不想弄乱initialize()
,可以尝试通过从Angular应用程序中获取SAFE_MODE
以及它是否位于{{1 }}(例如,可以通过简单的SAFE_MODE
搜索来检查),您可以尝试通过从缓存存储中删除所有项目然后取消注册服务工作者来重置它。这个想法是在a comment by mattlewis92中提出的,并在a comment by gkalpak中被认为是可行的hack。
正如已经发现shobhit vaish一样,您也可以手动解决此问题。除了原始帖子中已经说明的可能性之外,您还可以在基于Chrome的浏览器的开发工具中的“应用程序”->“清除存储”下,选择“取消注册服务人员”,然后单击“清除站点数据”。显然,该问题可以并且很可能会在将来的更新中重新出现,并且对普通用户没有太大帮助。但是,如果您作为开发人员现在只想快速解决它,这可能会很方便。