Angular 服务工作者 SwUpdate.available 未被触发

52

我在将angular的服务工作者集成到我的应用程序中遇到了困难。我按照指南操作,目前也能够使用。我可以在我的主屏幕上创建快捷方式并启动我的应用程序。问题在于我的应用程序似乎不更新。如果我更改按钮的名称,构建应用程序并将其放在服务器上,应用程序仍然显示旧版本,直到我按下F5(重新启动应用程序也没有帮助)。

我尝试将以下代码放入我的应用程序的ngOnInot中,但没有帮助

ngOnInit() {
if (this._SwUpdate.isEnabled) {

  setInterval( () => {
    this._SwUpdate.checkForUpdate().then(() => console.log('checking for updates'));
  }, this.updateInterval);

  this._SwUpdate.available.subscribe(() => {

    console.log('update found');

    this._SwUpdate.activateUpdate().then(() => {
      console.log('updated');
      window.location.reload();
    });

  });

}

}

这个应用正在我的apache2 Linux机器上运行。我的Apache是否缓存了什么,或者为什么我的应用程序没有意识到有一个新版本?

提前感谢您的帮助 :)

编辑:

My ngsw-config.json

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "roomPlan",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/index.html",
        "/*.css",
        "/*.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  }]
}

编辑2:

如果我使用“http-server”在本地运行应用程序,它可以工作,但是当我将文件复制到我的Apache上时,它无法检测到更新。在网络选项卡中,我可以看到间隔起作用,应用程序每3秒从服务器获取一个新的“ngsw.json”。如果我更新我的应用程序,我可以看到“ngsw.json”响应中有新的哈希值。此后,浏览器从服务器加载新的“index.html”和“main.***.js”,但应用程序不适用新版本。根据我的代码,它应该显示“发现更新”,但什么也没有发生。


Angular文档是最好的资源,关于这个,请参考此页面 - Pankaj Parkar
7个回答

61

你可能需要告诉Service Worker检查服务器是否有更新,我通常使用一个服务来实现这个:

export class UpdateService {

  constructor(public updates: SwUpdate) {
    if (updates.isEnabled) {
      interval(6 * 60 * 60).subscribe(() => updates.checkForUpdate()
        .then(() => console.log('checking for updates')));
    }
  }

  public checkForUpdates(): void {
    this.updates.available.subscribe(event => this.promptUser());
  }

  private promptUser(): void {
    console.log('updating to new version');
    this.updates.activateUpdate().then(() => document.location.reload()); 
  }

在你的 app-component.ts 文件中:

  constructor(private sw: UpdateService) {
    // check the service worker for updates
    this.sw.checkForUpdates();
  }
无论出于何种原因,Angular有时无法正确地注册服务工作者。因此,您可以修改 `main.ts`:

替换为:

platformBrowserDynamic().bootstrapModule(AppModule);

使用:

platformBrowserDynamic().bootstrapModule(AppModule).then(() => {
  if ('serviceWorker' in navigator && environment.production) {
    navigator.serviceWorker.register('ngsw-worker.js');
  }
}).catch(err => console.log(err));

2
我只是想确认一下SwUpdate... 我进入我的应用程序,在任何组件中编写"hello world",ng build --prod我的应用程序,将其复制到我的apache2中,服务工作程序应该会刷新它... 对吗? - user9973068
1
没错,是的,请检查您的域名.com/ngsw/state的调试日志,看看任务队列中是否有任何内容。 - Michael Doye
2
我刚刚完全重置了我的测试系统并设置了一个新的Apache服务器。在将您的修复应用于main.ts之后,现在一切都正常了,感谢您的帮助。 - user9973068
1
有时候服务工作者没有注册,只是因为你使用了 setInterval 并且应用从一开始就不稳定,因为它触发了 ngZOne 变化检测。为了避免这种情况,请在 Angular 之外运行所有间隔。 - Vytautas Pranskunas
1
@MichaelDoye 这个解决方案对于 Angular V8 仍然有效并且推荐吗?我注意到在更新后我的 IOS PWA 没有重新加载页面,这意味着它可能没有触发 activateUpdate()。 - Abner
显示剩余26条评论

9

8

在堆栈上的其他解决方案都无法解决问题后,我开始调试Angular的ngsw-worker.js脚本。我追踪了更新逻辑并最终到达了“PrefetchAssetGroup”方法。我在每次调用该方法时插入了日志记录,然后意识到它一直在尝试缓存我的favicon.ico图标。我检查了ngsw.json中favicon.ico的位置,并意识到图标没有放置在那里。一旦我把图标放在那个位置,一切都正常了。


0

如果您需要对应用程序进行更改,您需要使用此方法 activateUpdate()

import { SwUpdate } from '@angular/service-worker';

export class AppComponent implements OnInit {
  constructor(private swUpdate: SwUpdate) { }
  ngOninit() {
    this.swUpdate.available.subscribe(event => {
      console.log('A newer version is now available. Refresh the page now to update the cache');
    });
    this.swUpdate.checkForUpdate()
  }
}

请查看此链接:https://angular.io/guide/service-worker-getting-started

1
我按照你说的做了(保持一个空标签页并在更改后重新启动http-server),但服务工作者没有更新到新版本,我不得不完全关闭浏览器并重新启动才能获取最新版本。我的ngsw-config.json可能有什么问题吗? - user9973068
1
仍然无法工作,SwUpdate.available.subscribe从未被触发,但我不知道为什么。我在其中放置了console.log,但我永远看不到它。如果我构建我的应用程序并将其放置在我的服务器上,则服务工作者根本不会对其做出反应。 - user9973068
抱歉,您能将 this._swUpdate.checkForUpdate() 添加到您的 if 条件语句中吗? - Chellappan வ
我正在使用每10秒检查更新的间隔,但它没有响应新版本(我更新了我的代码示例)。 - user9973068
我不确定是否可以分享整个代码,因为这是一个内部项目。哪些文件可以提供帮助? - user9973068
显示剩余2条评论

0

我已经使用Michael Doye的答案中的解决方案一段时间了,但当我升级到Angular 14时它停止工作了。

下面的解决方案源自Vytautas Pranskunas的评论

在NgZone外部运行间隔

    constructor(public swUpdate: SwUpdate, private ngZone: NgZone) {

    if (swUpdate.isEnabled) {
      this.ngZone.runOutsideAngular(() =>
        interval(1000 * 10).subscribe(val => {
          swUpdate
            .checkForUpdate()
            .then(_ => console.log('SW Checking for updates'));
        })
      );
    }

(为测试目的每10秒检查一次-生产环境中应增加间隔)


-1

这对我在所有设备上都有效,包括Mac/Windows/iOS/Android。

export class PwaUpdateService {

    updateSubscription;

    constructor(public updates: SwUpdate) {
    }

    public checkForUpdates(): void {
        this.updateSubscription = this.updates.available.subscribe(event => this.promptUser());

        if (this.updates.isEnabled) {
            // Required to enable updates on Windows and ios.
            this.updates.activateUpdate();

            interval(60 * 60 * 1000).subscribe(() => {
                this.updates.checkForUpdate().then(() => {
                    // console.log('checking for updates');
                });
            });

        }

        // Important: on Safari (ios) Heroku doesn't auto redirect links to their https which allows the installation of the pwa like usual
        // but it deactivates the swUpdate. So make sure to open your pwa on safari like so: https://example.com then (install/add to home)
    }

    promptUser(): void {
        this.updates.activateUpdate().then(() => {
            window.location.reload();
        });
    }
}

-4

要检查是否有新版本的Angular可用,您可以从任何组件调用下面的方法,或者只需复制app.component中的IsNewerVersionAvailable方法。

export class DataService {
    
    constructor(private http: HttpClient, private swUpdate: SwUpdate) { }

    private available: boolean = false;
 
    IsNewerVersionAvailable() {
        if (this.swUpdate.isEnabled) {
            this.swUpdate.available.subscribe(() => {
                this.available = true;
            });
            console.log(this.available);
        }
        return this.available;
    }    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接