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

时间:2019-09-30 08:07:21

标签: angular caching service-worker progressive-web-apps

在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 个答案:

答案 0 :(得分:1)

您在performance的1天中使用maxAge模式,该模式总是从缓存中提供价值(如果有)。您将在一天后看到数据更改。

相反,您可以使用freshness模式或在maxAge模式下减小performance

您的手动完成请求不适用,因为URL https://my-api.com/v1/languages已缓存在服务工作者中。请求中的两种缓存操作都不起作用,因为请求缓存和服务工作者缓存是不同的缓存层。

从角度docs

  

Angular服务工作者可以使用两种缓存策略中的任何一种来获取数据资源。

     

性能(默认设置)会针对尽可能快的响应进行优化。如果缓存中存在资源,则使用缓存的版本,并且不发出网络请求。根据maxAge,这会有些陈旧,以换取更好的性能。这适用于不经常更改的资源。例如,用户头像图片。

     

新鲜度优化了数据流通性,优先从网络中获取请求的数据。只有网络超时(根据超时),请求才会回退到缓存。这对于经常变化的资源很有用;例如帐户余额。

答案 1 :(得分:1)

首先,您需要了解服务工作者层是与前端和服务器分离的。它位于中间,拦截所有网络请求,因此您可以决定如何处理它们。

服务工作者获取事件处理程序只有一个参数,事件。

您可以“解析”该对象以获取有关请求,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的缓存策略,则需要查看可能要应用的策略。 FWIW,我可能会采用大约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 );

    }
简而言之,您可以控制每个网络请求的处理方式,这就是服务工作者的美丽。您只需要创建逻辑来处理此问题,就没有神奇的子弹可以培养出色的服务人员。您将必须自己编写代码,当然还要对其进行测试。 :)