Я использую модуль TransferState для кэширования HTTP-ответа на стороне сервера, но, похоже, он не работает.
Что я сделал, так это добавил ServerTransferStateModule в AppServerModule и BrowserTransferStateModule в AppModule, как предлагается здесь https://next.angular.io/api/platform-browser/TransferState
Затем я добавил ниже перехватчик, который перехватывает каждый HTTP-запрос и:
на сервере выполняет запрос и сохраняет ответ в кеше.
когда на клиенте, проверьте кеш, если кешированный ответ существует, он возвращает его, в противном случае выполняет запрос.
import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformServer } from '@angular/common';
import { TransferState, makeStateKey } from '@angular/platform-browser';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { of } from "rxjs/observable/of";
import { catchError, tap } from 'rxjs/operators';
const CACHE_KEY = makeStateKey('httpCacheKey');
@Injectable()
export class MyInterceptor implements HttpInterceptor {
private isServer = isPlatformServer(this.platformId);
constructor(
@Inject(PLATFORM_ID) private platformId,
private transferState: TransferState,
@Inject('BASE_URL') private baseUrl: string) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let modifiedRequest: any;
let isLocalRequest: boolean = !req.url.startsWith('http');
if (isLocalRequest) {
//skip cache check if the request method isn't GET.
if (req.method == 'GET') {
// check and serve cached response, if it exists
const cachedResponse = this.transferState.get(CACHE_KEY, null as any);
if (cachedResponse) {
let modifiedResponse = new HttpResponse<any>({ headers: cachedResponse.headers, body: cachedResponse.body, status: cachedResponse.status, statusText: cachedResponse.statusText, url: cachedResponse.url });
return of(modifiedResponse);
}
}
// Clone the request to add the new header.
modifiedRequest = req.clone({ headers: req.headers, url: this.baseUrl + req.url, body: req.body });
}
return next.handle(isLocalRequest ? modifiedRequest : req)
.pipe(tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
if (this.isServer && isLocalRequest) {
this.transferState.set(CACHE_KEY, event as any);
}
}
}));
}
}
Я вижу, что ответ кэшируется и передается клиенту, я вижу ниже тег скрипта в разметке, возвращаемой с сервера:
<script id="ng-cli-universal-state" type="application/json">{&q;httpCacheKey&q;:{&q;headers&q;:{&q;normalizedNames&q;:{},&q;lazyUpdate&q;:null},&q;status&q;:200,&q;statusText&q;:&q;OK&q;,&q;url&q;:&q;http://localhost:49805/api/SampleData/WeatherForecasts&q;,&q;ok&q;:true,&q;type&q;:4,&q;body&q;:[{&q;dateFormatted&q;:&q;11/28/2017&q;,&q;temperatureC&q;:28,&q;summary&q;:&q;Mild&q;,&q;temperatureF&q;:82},{&q;dateFormatted&q;:&q;11/29/2017&q;,&q;temperatureC&q;:-15,&q;summary&q;:&q;Balmy&q;,&q;temperatureF&q;:6},{&q;dateFormatted&q;:&q;11/30/2017&q;,&q;temperatureC&q;:51,&q;summary&q;:&q;Freezing&q;,&q;temperatureF&q;:123},{&q;dateFormatted&q;:&q;12/1/2017&q;,&q;temperatureC&q;:45,&q;summary&q;:&q;Mild&q;,&q;temperatureF&q;:112},{&q;dateFormatted&q;:&q;12/2/2017&q;,&q;temperatureC&q;:1,&q;summary&q;:&q;Mild&q;,&q;temperatureF&q;:33}]}}</script>
Но http-запросы выполняются дважды, один раз на сервере и снова в браузере.