使用TransferState模块的Angular 5服务器端渲染似乎无法正常工作

时间:2017-11-28 15:06:18

标签: angular-universal angular5

我正在使用TransferState模块在服务器端缓存http响应,但它似乎无法正常工作。

我所做的是什么,加入的 ServerTransferStateModule AppServerModule BrowserTransferStateModule 的AppModule 作为此处建议{{3 }}

然后我在拦截器下面添加拦截器,拦截每个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请求执行两次,一次在服务器上,另一次在浏览器中。

1 个答案:

答案 0 :(得分:2)

我遇到了同样的问题。在this tutorial结束时找到了解决方案。在DOMContentLoaded事件触发后,您需要确保引导App Module。

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