Angular PWA не кеширует запросы к серверу

Я сделал сайт, который должен работать и как PWA с Angular 8. Я также использовал Angular Universal для SSR. Работает, даже офлайн. Проблема в том, что кешируется только сайт, но не запросы к серверу. Я добавил dataGroups в настройки ngsw.

Это мой ngsw-config.json

{
  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
  "index": "/index.html",
  "dataGroups": [
    {
      "name": "exercises-requests",
      "urls": [
        "/api/provide-exercise"
      ],
      "cacheConfig": {
        "strategy": "performance",
        "maxSize": 100,
        "maxAge": "3d"
      }
    }
  ],
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html",
          "/*.css",
          "/*.js"
        ]
      }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
        ]
      }
    }
  ]
}

Это мой http-сервис:

import { Injectable, isDevMode } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { throwError, Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Input } from '../exercise/exercise.service';

export interface UserInfo {
  // ...
}
export interface ProvideExerciseBody {
  // ...
}
export interface ProvideExerciseResponse {
  // ...
}

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json'
  })
};

@Injectable({
  providedIn: 'root',
})
export class HttpService {

  get
  serverDomain(): string {
    return isDevMode() ? 'https://unitn-statistica.herokuapp.com' : '';
  }

  constructor(private http: HttpClient) { }

  provideExercise(body: ProvideExerciseBody): Observable<ProvideExerciseResponse> {
    return this.http.post<ProvideExerciseResponse>(this.serverDomain + '/api/provide-exercise', body, httpOptions)
      .pipe(
        catchError(this.handleError)
      );
  }

  private handleError(err: HttpErrorResponse) {
    const error = err.error;
    if (error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.message);
      console.error(error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(
        `Backend returned code ${err.status}, ` +
        `body was: ${error}`);
      console.log(error);
    }
    // return an observable with a user-facing error message
    return throwError(error.message);
  }

}

И я уверен, что вызов сервера правильный

app.post('/api/provide-exercise', (req, res) => { ... }

Я не понимаю, почему мои почтовые запросы к серверу не кэшируются.


person EuberDeveloper    schedule 18.06.2019    source источник


Ответы (1)


Я думаю, что проблема, с которой вы столкнулись, заключается в том, что запросы POST не кэшируются сервисным работником Angular, независимо от того, как он был настроен. Причина в том, что запрос POST обычно предназначен для изменения ресурса на сервере. Поэтому не очень полезно кэшировать этот запрос.

Это важная часть кода, исключающая любые изменяющие запросы: https://github.com/angular/angular/blob/master/packages/service-worker/worker/src/data.ts#L283.

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

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

person chrisguttandin    schedule 18.06.2019
comment
Я думаю, вы тесны. Проблема вот в чем: сайты просят поставить (фиксированный для всех) юзер и пароль, и дату. Сервер проверяет пароль пользователя и возвращает упражнение этой даты. Передавая также зарезервированные данные, такие как пользователь и пароль, я должен использовать POST. Но это мешает мне кэшировать упражнение, поэтому pwa становится бесполезным, поскольку каждый вызов упражнения завершается ошибкой. Как я могу быть уверен, что с локальным хранилищем данные сохранятся? - person EuberDeveloper; 19.06.2019
comment
Вы не можете быть на 100% уверены, что данные сохранятся. Как и любые другие пользовательские данные, пользователь может решить удалить их в любой момент времени. Но это справедливо и для кеша сервис-воркера. Но я думаю, что тот, кто загружает/устанавливает PWA, не хочет удалять данные. - person chrisguttandin; 19.06.2019