10

index.html每次我对Angular 项目进行任何更改时,Service Worker 都不会更新,并且总是在index.html. 我该如何解决这个问题(另外,服务器端和浏览器都没有缓存)

这是我的ngsw-config文件:

    {
      "index": "/index.html",
      "assetGroups": [{
        "name": "app",
        "installMode": "prefetch",
        "resources": {
          "files": [
            "/favicon.ico",
            "/index.html",
            "/manifest.json"
          ],
          "versionedFiles": [
            "/*.bundle.css",
            "/*.bundle.js",
            "/*.chunk.js"
          ]
        }
      }, {
        "name": "assets",
        "installMode": "lazy",
        "updateMode": "prefetch",
        "resources": {
          "files": [
            "/assets/**"
          ]
        }
      }]
    }

我对请求的响应标头:

我对我的 Angular APP 的请求的屏幕截图

知道如何解决这个问题吗?

谢谢

4

2 回答 2

5

我认为问题出在 ngsw-config 中。如果 dist 文件夹中的.css.js文件的名称中没有.bundle.chunk ,则.css.js条目versionedFiles可能与它们不匹配 。在更新的 Angular 版本中,这些条目被替换为and ,并且dist文件夹中的文件在构建生产时没有.bundle.chunk 。"/*.js""/*.css"

因此,问题实际上是.js.css文件没有被缓存,并且每当服务器上的文件更新时,应用程序不再找到它们并且浏览器在之前抛出错误(因为它返回 index.html)服务工作者可以加载“缓存”文件,检测更改并更新文件。

在 Angular 6 中,versionedFiles行为files与已弃用相同。因此,您的 ngsw-config.json 应该如下所示:

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/manifest.json",
        "/*.css",
        "/*.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  }]
}
于 2018-06-08T05:24:15.670 回答
4

您可以在 service worker 中使用如下代码强制 service worker 删除所有以前的 SW 缓存(也包括 index.html):

const DIRTY_CACHE = 'application-version-number-or-whatever';

self.addEventListener('install', () => { 
  // Skip over the "waiting" lifecycle state, to ensure that our 
  // new service worker is activated immediately, even if there's 
  // another tab open controlled by our older service worker code. 
  self.skipWaiting(); 
});

self.addEventListener('activate', event => {
  self.registration.unregister();
  event.waitUntil(
    caches
      .keys()
      .then(cacheNames =>
        cacheNames.filter(cacheName => cacheName.indexOf(DIRTY_CACHE) !== -1),
      )
      .then(cachesToDelete =>
        Promise.all(
          cachesToDelete.map(cacheToDelete => caches.delete(cacheToDelete)),
        ),
      )
      .then(() => self.clients.claim()),
  );
});

更详细的解释可以在这篇文章中找到

也许不是最好的策略,但可以解决问题,可能是由于过期标头错误。

于 2018-12-13T16:55:16.080 回答