Angular PWA 不缓存服务器请求
Angular PWA not caching server requests
我制作了一个网站,它应该也可以作为 PWA 使用 Angular 8。我也使用 Angular Universal for 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) => { ... }
我不明白为什么我对服务器的 post 请求没有被缓存。
我认为您面临的问题是 POST 请求不会被 Angular 的 Service Worker 缓存,无论它是如何配置的。原因是 POST 请求通常意味着改变服务器上的资源。因此缓存这个请求并没有多大用处。
这是排除任何变异请求的代码的相关部分:https://github.com/angular/angular/blob/master/packages/service-worker/worker/src/data.ts#L283
也许您可以控制服务器并且您发出的请求不会改变任何内容。那么使用 GET 请求可能是一个很好的解决方案。
但是,如果请求确实在改变某些东西,但您仍然想缓存响应,那么使用其他缓存策略(例如 localStorage
或 IndexedDB
.
可能是一种解决方案
我制作了一个网站,它应该也可以作为 PWA 使用 Angular 8。我也使用 Angular Universal for 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) => { ... }
我不明白为什么我对服务器的 post 请求没有被缓存。
我认为您面临的问题是 POST 请求不会被 Angular 的 Service Worker 缓存,无论它是如何配置的。原因是 POST 请求通常意味着改变服务器上的资源。因此缓存这个请求并没有多大用处。
这是排除任何变异请求的代码的相关部分:https://github.com/angular/angular/blob/master/packages/service-worker/worker/src/data.ts#L283
也许您可以控制服务器并且您发出的请求不会改变任何内容。那么使用 GET 请求可能是一个很好的解决方案。
但是,如果请求确实在改变某些东西,但您仍然想缓存响应,那么使用其他缓存策略(例如 localStorage
或 IndexedDB
.