Angular 5 使用 TransferState 模块的服务器端呈现似乎无法正常工作
Angular 5 Server Side Rendering with TransferState Module doesn't seem to be working properly
我正在使用 TransferState 模块在服务器端缓存 http 响应,但它似乎不起作用。
我所做的是,将 ServerTransferStateModule 添加到 AppServerModule 并将 BrowserTransferStateModule 添加到 AppModule 此处建议 https://next.angular.io/api/platform-browser/TransferState
然后我在下面添加了拦截器,拦截每个http请求并且:
在服务器上时,执行请求并将响应存储在缓存中。
在客户端时,检查缓存是否存在缓存响应,returns否则执行请求。
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 请求执行了两次,一次在服务器上,一次在浏览器中。
我遇到了同样的问题。在 this tutorial 的末尾找到解决方案。您需要确保在 DOMContentLoaded 事件触发后引导您的应用程序模块。
main.ts
:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
// Listen for the event before bootstrapping:
document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
});
我正在使用 TransferState 模块在服务器端缓存 http 响应,但它似乎不起作用。
我所做的是,将 ServerTransferStateModule 添加到 AppServerModule 并将 BrowserTransferStateModule 添加到 AppModule 此处建议 https://next.angular.io/api/platform-browser/TransferState
然后我在下面添加了拦截器,拦截每个http请求并且:
在服务器上时,执行请求并将响应存储在缓存中。
在客户端时,检查缓存是否存在缓存响应,returns否则执行请求。
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 请求执行了两次,一次在服务器上,一次在浏览器中。
我遇到了同样的问题。在 this tutorial 的末尾找到解决方案。您需要确保在 DOMContentLoaded 事件触发后引导您的应用程序模块。
main.ts
:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
// Listen for the event before bootstrapping:
document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
});