PWA:排除应用程序某些部分的缓存

3
在一个Angular应用中,我有一个URL端点正在被缓存,代码如下:
// ngsw-config.json
"dataGroups": [{
      "name": "api-performance",
      "urls": [
        "https://my-api.com/v1/languages",
      ],
      "cacheConfig": {
        "strategy": "performance",
        "maxSize": 300,
        "maxAge": "1d"
      }
    }
  ]

在客户端进行调查过程时,离线场景下它运行得非常完美。但是在管理面板中,当我尝试更新语言信息时,确实会更新数据库中的记录,但是当我尝试刷新数据时,它不会向我们的端点发送请求,而是发送到浏览器中存储的缓存中。
这是我尝试过的方法:
getLanguages(shouldCache: boolean): Promise<any> {
    if (shouldCache) {
      return this.httpClient.get('https://my-api.com/v1/languages').toPromise();
    } else {
      const headers = new HttpHeaders({
        'Cache-Control': 'no-cache, no-store, must-revalidate, post-check=0, pre-check=0',
        'Pragma': 'no-cache',
        'Expires': '0'
      });
      return this.httpClient.get('https://my-api.com/v1/languages', { headers: headers }).toPromise();
    }
  }

很遗憾,它不起作用。我考虑过更新缓存,但我不知道如何做。

有人有什么想法来解决这个问题吗?

2个回答

2
您正在使用1天的maxAgeperformance模式,如果可用,它将始终从缓存中获取值。一天后您将看到数据更改。

相反,您可以使用freshness模式或减少performance模式中的maxAge

由于URLhttps://my-api.com/v1/languages已经被缓存在服务工作者中,因此您手动发出的请求不适用。请求缓存和服务工作者缓存是不同的缓存层,因此在请求中进行缓存操作也无效。

来自Angular 文档

Angular服务工作者可以使用两种缓存策略来处理数据资源。
默认情况下,性能优化响应速度尽可能快。如果一个资源存在于缓存中,则使用缓存版本,不进行网络请求。这允许一定程度的陈旧,取决于最大年龄,以换取更好的性能。这适用于不经常更改的资源,例如用户头像图片。 新鲜度优化数据的实时性,优先从网络获取所请求的数据。只有当网络超时(根据超时时间)时,才会回退到缓存。这对于经常更改的资源非常有用,例如账户余额。

0
首先,你需要明白服务工作线程层与前端和服务器是解耦的。它位于中间并拦截所有网络请求,因此你可以决定如何处理它们。
服务工作线程的fetch事件处理程序只有一个参数,即event。
你可以“解析”这个对象以获取有关请求的信息,例如event.request,并决定如何处理事务。
例如,你很可能不希望缓存POST、PUT或DELETE请求,所以只需通过调用fetch将它们传递给网络。为了简化操作,只测试GET请求即可。
self.addEventListener("fetch", event => {

  event.respondWith(

    if(event.request.mode === "GET") {

      //compare URL against rules table
      //perform caching strategy for this URL

    } else {

      return fetch(event);

    }
  );
});

如果您可能有一个适用于URL的缓存策略,那么您需要看看您可能想要应用的策略。顺便说一下,我有大约25种不同的策略可以使用,所以我会尽量保持简单。

这是一个示例,用于将URL与缓存策略进行匹配的方法:

function testRequestRule( request, rules ) {

  for ( let i = 0; i < rules.length; i++ ) {

      if ( rules[ i ].route && rules[ i ].route.test( request.url ) ) {
          return rules[ i ];
      } else if ( rules[ i ].destination &&
          rules[ i ].destination === request.destination ) {
          return rules[ i ];
      }

  }

}

这是一个规则对象可能的样子:
let routeRules = [ {
    "route": /img\/products\//,
    "strategy": "cacheFallingBackToNetworkCache",
    "options": {
        cacheName: prodPhotos,
        fallback: offlineProductPhoto
    }
},....]

然后我将根据请求执行所需的策略。
    if ( rule.strategy ) {

        switch ( rule.strategy ) {

            case "cacheFallingBackToNetwork":

                return responseManager.cacheFallingBackToNetworkCache(
                    event.request, rule.cacheName || cacheName,
                    rule.options.fallback );

            case "fetchAndRenderResponseCache":

                return responseManager.fetchAndRenderResponseCache( {
                        request: event.request,
                        pageURL: rule.options.pageURL,
                        template: rule.options.template,
                        api: rule.options.api,
                        cacheName: rule.cacheName || cacheName
                    } )
                    .then( response => {

                        invalidationManager.cacheCleanUp( rule.cacheName || cacheName );

                        return response;

                    } );

            case "cacheOnly":

                return responseManager.cacheOnly( event.request, rule.cacheName || cacheName )
                    .then( response => {

                        invalidationManager.cacheCleanUp( rule.cacheName || cacheName );

                        return response;

                    } );

            case "networkOnly":

                return responseManager.networkOnly( event.request );

            case "custom":

                return rule.options.handler( event, rule );

            default:

                return responseManager
                    .cacheFallingBackToNetworkCache( event.request,
                        rule.cacheName || cacheName,
                        rule.options.fallback )
                    .then( response => {

                        invalidationManager.cacheCleanUp( rule.cacheName || cacheName );

                        if ( response ) {
                            return response;
                        } else {
                            return simpleFetch( event );
                        }

                    } )
                    .catch( error => {
                        console.error( "fetch error: ", error );
                        console.error( "url: ", event.request.url );
                    } );

        }

    } else {

        return simpleFetch( event );

    }

简而言之,你可以控制每个网络请求的处理方式,这就是 Service Worker 的美妙之处。你只需要创建适当的逻辑来处理它,没有什么捷径可以让一个好的 Service Worker 诞生。你必须亲自编写代码,并进行测试。 :)

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