9gt*_*3wS 7 progressive-web-apps angular aws-amplify
我在生产中有一个 Angular 8 PWA 应用程序。我定期进行大量更新,因此我需要找到一种方法让用户在打开应用程序时获取这些更新。
如果没有特殊操作,应用程序将不会更新。如果您在浏览器上打开该应用程序,它会显示您上次打开该应用程序时的版本,即使我已将新捆绑包推送到生产环境。这似乎是 PWA 功能的不幸结果。
我使用 AWS Amplify 进行托管。
为了解决这个问题(我在这里问过一个问题),我尝试使用 swUpdate。
问题是它的工作速度太慢了。如果有更新,它会重新加载浏览器——但这需要一段时间。用户打开应用程序后通常需要几秒钟才能重新加载。所以你打开应用程序,4 到 6 秒后应用程序重新加载新版本。
有没有办法让 swUpdate 运行得更快?或者加载新应用程序版本的替代方法?
这是我的代码,我认为这是一个简单的实现:
app.component.ts:
import { Component } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(private swUpdate: SwUpdate) {
title = 'Great App'
swUpdate.available.subscribe(event => {
swUpdate.activateUpdate().then(() => {
window.location.reload();
console.log('there is an Update! Reloading now.')
});
})
if (!this.swUpdate.isEnabled) {
console.log('Not going to update');
}
}
Run Code Online (Sandbox Code Playgroud)
但这效果不佳,因为重新加载通常在用户访问应用程序后几秒钟发生(即使在良好的互联网连接下)。
我知道我还可以向人们显示一条消息,说“想要刷新新版本?” 但这并不能解决 swUpdate 当前工作缓慢的根本问题。
Angular 中的 Service Worker 有 4 种不同的注册策略,这决定了它何时向浏览器注册。
registerWhenStable:<timeout>:应用程序稳定后立即注册(无待处理的微/宏任务),但不晚于毫秒。如果应用程序在几毫秒后仍未稳定(例如,由于重复的异步任务),ServiceWorker 无论如何都会被注册。如果省略,则只有在应用程序稳定后才会注册 ServiceWorker。registerImmediately: 立即注册。registerWithDelay:<timeout>:延迟毫秒注册。例如,使用registerWithDelay:5000在5秒后注册ServiceWorker。如果省略,则默认为 0,一旦所有挂起的微任务完成,它将尽快注册 ServiceWorker,但仍然是异步的。An Observable factory function:返回 Observable 的函数。该函数将在运行时用于获取并订阅 Observable,并且 ServiceWorker 将在第一个值发出后立即注册。注意:AngularregisterWhenStable:30000默认使用. 这意味着它将首先等待应用程序稳定下来,然后注册一个 Service Worker(或者如果应用程序在此之前尚未稳定,它将在 30 秒后注册 Service Worker)。
registerWhenStable:30000您可以设置registerImmediately策略而不是默认值。然后您可以添加APP_INITIALIZER并在其中检查是否有新版本并加载它。在这种情况下,如果有新版本可用,用户将看不到旧版本。
应用程序模块.ts
import { APP_INITIALIZER } from '@angular/core';
import { ServiceWorkerModule, SwUpdate } from '@angular/service-worker';
...
function initializeApp(): Promise<any> {
return new Promise(async (resolve, reject) => {
try {
// Check if Service Worker is supported by the Browser
if (this.swUpdate.isEnabled) {
const isNewVersion = await this.swUpdate.checkForUpdate();
// Check if the new version is available
if (isNewVersion) {
const isNewVersionActivated = await this.swUpdate.activateUpdate();
// Check if the new version is activated and reload the app if it is
if (isNewVersionActivated) window.location.reload();
resolve(true);
}
resolve(true);
}
resolve(true);
} catch (error) {
window.location.reload();
}
});
}
...
@NgModule({
...
imports: [
...,
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
registrationStrategy: 'registerImmediately',
}),
],
providers: [
...,
{ provide: APP_INITIALIZER, useFactory: initializeApp, deps: [SwUpdate], multi: true },
],
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
387 次 |
| 最近记录: |