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));
});