PWA: исключить кэширование в некоторой части приложения - PullRequest
2 голосов
/ 30 сентября 2019

В приложении 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 ]

1 голос
/ 30 сентября 2019

Во-первых, вы должны понимать, что рабочий слой службы отделен от внешнего интерфейса и вашего сервера. Он находится посередине и перехватывает все сетевые запросы, чтобы вы могли решить, как они будут обрабатываться.

У обработчика события выборки работника службы есть один аргумент, событие.

Вы можете «проанализировать»этот объект для получения информации о запросе, 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 );

    }

Короче говоря, вы можете контролировать, как каждыйСетевой запрос обрабатывается, это красота работника службы. Вы просто должны создать логику, чтобы справиться с этим, и нет никаких волшебных способностей, чтобы сделать хорошего работника сервиса. Вы должны будете написать код самостоятельно и, конечно, протестировать его. :)

1 голос
/ 30 сентября 2019

Вы используете режим performance с 1 днем ​​maxAge, который всегда дает значение из кэша, если доступно. Вы увидите изменение данных через один день.

Вместо этого вы можете использовать режим freshness или уменьшить maxAge в режиме performance.

Ваш ручной запрос не применяется,потому что URL https://my-api.com/v1/languages кэшируется в сервисном работнике. Любая манипуляция с кешем в запросе не будет работать, потому что кеш запросов и кеш рабочего сервиса - это разные уровни кеша.

From Angular docs :

Служба AngularРаботник может использовать любую из двух стратегий кэширования для ресурсов данных.

производительность , используемая по умолчанию, оптимизирует ответы как можно быстрее. Если ресурс существует в кэше, используется кэшированная версия, и сетевой запрос не выполняется. Это учитывает некоторую стабильность, в зависимости от maxAge, в обмен на лучшую производительность. Это подходит для ресурсов, которые не меняются часто;например, изображения аватара пользователя.

свежесть оптимизирует для валюты данных, преимущественно выбирая запрошенные данные из сети. Только в случае тайм-аута сети, согласно тайм-ауту, запрос возвращается к кешу. Это полезно для ресурсов, которые часто меняются;например, остатки на счетах.

...