Angular service worker 在 Github 页面(子目录)上部署后不会缓存资产

Angular service worker doesn't cache assets once deployed on Github pages (sub-directory)

我开发了一个 Angular PWA 演示应用程序 (Angular v9.1.3),实现了 performancefreshness 策略。

它在本地完美运行,即使离线也是如此。但是一旦部署在 Github 页面上,它就不再像预期的那样工作了:

  1. performance 策略不断从网络中获取所有请求,而不是从缓存中获取
  2. 离线后,应用程序无法运行,因为似乎没有缓存任何内容


我使用 angular-cli-ghpages 通过以下命令部署到 gh-pages(angular-pwa-boilerplate 是 Repo 名称):

    ng deploy --base-href=/angular-pwa-boilerplate/


部署后,我将 web-manifest 文件的 start_url 属性 调整为“/angular-pwa-boilerplate/”以反映子目录结构。

即使范围路径看起来是正确的并且应用程序是可安装的,服务工作人员也不会缓存资产或 Http 响应(虽然在本地一切都很好)。

我读了很多关于它的文章,但所有的修复都不起作用:

  1. 为服务工作者文件使用相对路径./
    ServiceWorkerModule.register('./ngsw-worker.js', ...)
  2. 在清单文件中设置作用域和 start_url 的相对值:
    "scope": ".",
    "start_url":" "./"


这里是DEMO and Github Repo

这个话题好像还有some ongoing work


更新

我注意到,如果我离开 start_url: "/"(因此没有将其调整为 base-href),Angular Service Worker 及其缓存策略在 gh-pages 上也很有效。


但是该应用程序无法再安装:

这是您访问 debug info 时看到的内容:

NGSW Debug Info:

Driver state: EXISTING_CLIENTS_ONLY (Degraded due to: Hash mismatch (cacheBustedFetchFromNetwork): https://pacoita.github.io/angular-pwa-boilerplate/manifest.webmanifest: expected cbcd3fc3623610507d05fab49a40b0fcb22f47bb, got 69c8bc4c8eb903528013fe49ac2c8a521b120901 (after cache busting)
Error: Hash mismatch (cacheBustedFetchFromNetwork): https://pacoita.github.io/angular-pwa-boilerplate/manifest.webmanifest: expected cbcd3fc3623610507d05fab49a40b0fcb22f47bb, got 69c8bc4c8eb903528013fe49ac2c8a521b120901 (after cache busting)
    at PrefetchAssetGroup.<anonymous> (https://pacoita.github.io/angular-pwa-boilerplate/ngsw-worker.js:734:35)
    at Generator.next (<anonymous>)
    at fulfilled (https://pacoita.github.io/angular-pwa-boilerplate/ngsw-worker.js:174:62))
Latest manifest hash: 4f36c4b0eb2e39ccabb57986bc3191e39cabad0c
Last update check: 1m45s215u

=== Version 4f36c4b0eb2e39ccabb57986bc3191e39cabad0c ===

Clients: 

=== Idle Task Queue ===
Last update tick: 1m50s390u
Last update run: 1m45s381u
Task queue:


Debug log:

[2m40s282u] Ignoring invalid request: 'only-if-cached' can be set only with 'same-origin' mode Driver.fetch(https://pacoita.github.io/angular-pwa-boilerplate/, cache: only-if-cached, mode: no-cors)
[2m34s503u] Error(Hash mismatch (cacheBustedFetchFromNetwork): https://pacoita.github.io/angular-pwa-boilerplate/manifest.webmanifest: expected cbcd3fc3623610507d05fab49a40b0fcb22f47bb, got 69c8bc4c8eb903528013fe49ac2c8a521b120901 (after cache busting), Error: Hash mismatch (cacheBustedFetchFromNetwork): https://pacoita.github.io/angular-pwa-boilerplate/manifest.webmanifest: expected cbcd3fc3623610507d05fab49a40b0fcb22f47bb, got 69c8bc4c8eb903528013fe49ac2c8a521b120901 (after cache busting)
    at PrefetchAssetGroup.<anonymous> (https://pacoita.github.io/angular-pwa-boilerplate/ngsw-worker.js:734:35)
    at Generator.next (<anonymous>)
    at fulfilled (https://pacoita.github.io/angular-pwa-boilerplate/ngsw-worker.js:174:62)) initializeFully for 4f36c4b0eb2e39ccabb57986bc3191e39cabad0c
[2m6s104u] TypeError(Failed to fetch, TypeError: Failed to fetch) Driver.fetch(https://pacoita.github.io/angular-pwa-boilerplate/)

笔记: 调试信息通常以 /ngsw/state 的形式提供,但在从子路径提供服务时这不起作用。这将通过 angular/angular#31082 修复。我只是破解了调试信息的方式。

根据调试信息,manifest.webmanifest 似乎存在哈希不匹配,这导致 ServiceWorker 无法正常工作。这意味着提供给浏览器的文件内容与生成 ngsw.json 文件时(在 ng build 期间)的文件内容不同。这是因为你在构建后修改文件。

为了避免这种情况,您应该在构建之前修改源文件(并让更改传播到构建的工件。

您是否也尝试过使用 ng build--baseHref 选项(即 ng build --prod --baseHref=/angular-pwa-boilerplate/ ...)?这应该负责自动更新任何 URL(包括 manigest.webmanifest)。