Cro*_*csx 10 javascript deployment service-worker angular
我正在使用 Angular 12,并使用 Service Worker 来部署新版本。
看起来每次我将新版本部署到生产环境时(并且由于某种原因不在暂存阶段)。一些用户收到一堆错误,例如
未捕获(承诺):ChunkLoadError:加载块 XXX 失败。
关于这个问题有很多帖子,但在我看来,解决方案是个案的。
与 stg 相比,我在生产方面的差异只是而已。
我打电话
enableProdMode();
我的服务人员设置如下:
ServiceWorkerModule.register('ngsw-worker.js', {
enabled:
environment.env === Environment.PRODUCTION || environment.env === Environment.STAGING,
registrationStrategy: 'registerWhenStable:30000',
}),
Run Code Online (Sandbox Code Playgroud)
我的配置看起来像
{
"$schema": "../../node_modules/@angular/service-worker/config/schema.json",
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": ["/favicon.ico", "/index.html", "/manifest.webmanifest", "/*.css", "/*.js"]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "lazy",
"resources": {
"files": ["/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"]
}
}
]
}
Run Code Online (Sandbox Code Playgroud)
这就是我显示更新的方式(基本上是一个可以忽略的横幅):
@Component({
selector: 'app-live-update-notifier',
templateUrl: './live-update-notifier.component.html',
styleUrls: ['./live-update-notifier.component.scss'],
})
export class LiveUpdateNotifierComponent implements OnDestroy {
hasUpdate = false;
isIgnored = false;
private subscription = new SubSink();
constructor(
@Inject(DOCUMENT) private document: Document,
private swUpdate: SwUpdate,
private appRef: ApplicationRef,
private changeDetectorRef: ChangeDetectorRef
) {
const appIsStable$ = this.appRef.isStable.pipe(first((isStable) => isStable === true));
const everySixHours$ = interval(6 * 60 * 60 * 1000);
const everySixHoursOnceAppIsStable$ = concat(appIsStable$, everySixHours$);
if (swUpdate.isEnabled) {
this.subscription.add(
everySixHoursOnceAppIsStable$.subscribe(() => swUpdate.checkForUpdate()),
this.swUpdate.available.subscribe((evt) => {
if (evt.type === 'UPDATE_AVAILABLE') {
this.hasUpdate = true;
this.changeDetectorRef.detectChanges();
}
})
);
}
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
updateApp() {
this.document.location.reload();
}
skipNotification() {
this.isIgnored = true;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您有任何可以指导解决方案的线索,谢谢。
编辑 :
我的应用程序中有一堆延迟加载的模块。我认为原因是某些模块在新版本之前没有加载,当用户在部署后导航到它们时,他们会遇到这个块问题。但我尝试通过以下方式模拟这个问题
所以我不认为这是这个问题
这可能是由不同的原因引起的。但由于spock123 ,我几个月前使用了一种解决方法。
我引用他的话:
当然,我们使用 Service Worker 服务
swUpdate来在新版本可用时获取通知。然而,当有新的软件版本时,有时似乎并非所有延迟加载的块都会更新。
基本上,解决方法是在遇到bundle not found导致错误的错误时重新加载应用程序ChunkLoadError。
您必须全局监听错误,如果应用程序遇到此错误,您只需重新加载页面即可。
我从angular.io引用:
在某些情况下,服务工作线程用于为客户端提供服务的应用程序版本可能处于损坏状态,如果不重新加载整页,则无法恢复该状态。
例如,想象以下场景:
index.html、main.<main-hash-1>.js和lazy-chunk.<lazy-hash-1>.js。index.html、main.<main-hash-2>.js和lazy-chunk.<lazy-hash-2>.js(请注意,哈希值现在不同,因为文件的内容发生了变化)。旧版本在服务器上不再可用。lazy-chunk.<lazy-hash-1>.js从缓存中删除。浏览器可能决定从缓存中逐出特定(或全部)资源,以回收磁盘空间。index.html和main.<main-hash-1>.js)。lazy-chunk.<lazy-hash-1>.js.lazy-chunk.<lazy-hash-2>.js从较新的版本获取)。在前面的场景中,服务工作线程无法提供通常会被缓存的资产。该特定应用程序版本已损坏,并且无法在不重新加载页面的情况下修复客户端的状态。在这种情况下,Service Worker 通过发送UnrecoverableStateEvent事件来通知客户端。订阅SwUpdate#unrecoverable即可收到通知并处理这些错误。
处理不可恢复状态.service.ts:
@Injectable()
export class HandleUnrecoverableStateService {
constructor(updates: SwUpdate) {
updates.unrecoverable.subscribe(event => {
notifyUser(
'An error occurred that we cannot recover from:\n' +
event.reason +
'\n\nPlease reload the page.'
);
});
}
}
Run Code Online (Sandbox Code Playgroud)