浏览器在部署新版本后看到 Angular 应用程序的旧版本,即使在清除缓存后也是如此

Browser sees old version of Angular app after new version is deployed, even after clearing cache

我有一个 Angular 11 应用程序,我正在使用以下命令构建用于生产部署的应用程序:

npm install
npm run build -- --prod --outputHashing=all

我遇到的问题是,部署后,当我使用浏览器访问应用程序 URL 时,我仍然看到该应用程序的旧版本。

我最初认为这是一个缓存问题,即使我正在使用 --outputHashing=all 选项进行编译(据我所知,它似乎正在工作,dist 文件夹中的输出文件具有看似随机的文件名)。似乎是这样:如果我在 Chrome 的开发选项中禁用缓存后刷新页面,它现在会显示更新的应用程序。

但是,问题来了:如果我关闭浏览器并再次打开它...我又会看到旧应用程序!因此,清除缓存似乎是一种临时解决方案。

经过进一步调查,我怀疑它与angular的service workers有关,因为当我打开Chrome的开发工具加载页面时,我可以看到很多网络调用被标记为Served from service worker.

但是,我在 Angular 方面还不够专业,不知道如何进一步诊断。我已经在 angular 的网站上阅读了有关 service workers 的文档,但它并没有帮助我找出问题的确切所在。谁能指出我正确的方向?这是我的 service worker 配置文件,它是在创建应用程序时自动生成的。如果我还应该提供其他文件,请告诉我:

{
  "$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": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
        ]
      }
    }
  ]
}

如果有任何不同,该应用程序托管在 .NET Core 服务中 运行 嵌入式 Katana 网络服务器,但它看不出这会有什么不同,它只是提供文件而没有进一步操纵。

连文件名都经过哈希处理,也帮不上什么忙。唯一的方法就是按 Ctrl + Shift + R 进行硬刷新或任何硬刷新是唯一的方法,在 javascript 中,location.reload() 是函数。

好消息是我们有 PWA(服务工作者)可以在您的浏览器上检测您网站的所有更改。

只需添加 ng add @angular/pwa 即可与 Service Worker 集成。

并使用它检测变化。

此代码为app.component.ts

  hasUpdate = false;

  constructor(
    private swUpdate: SwUpdate,
  ) {
  }

  ngOnInit(): void {
    // check for platform update
    if (this.swUpdate.isEnabled) {
      interval(60000).subscribe(() => this.swUpdate.checkForUpdate().then(() => {
        // checking for updates
      }));
    }
    this.swUpdate.available.subscribe(() => {
      this.hasUpdate = true;
    });
  }

  reloadSite(): void {
    location.reload();
  }

当有 hasUpdatetrue 时,你可以向用户显示一些警告消息,当用户 select 该消息时,你可以调用函数 location.reload

<div *ngIf="hasUpdate">
  <button (click)="reloadSite()">Reload</button>
</div>

这是处理此缓存问题的最佳方法。