node.js - TransferHttpCacheModule 不会阻止 Angular 8 中的重复 HTTP 调用

标签 node.js angular angular-universal

我已经使用 Angular Universal 建立了一个 Angular 8 项目。为了防止重复的 HTTP 调用,Angular 提供了 TransferHttpCacheModule

我按照官方文档将 TransferHttpCacheModule 添加到 Angular ( https://github.com/angular/universal/blob/master/docs/transfer-http.md )

我还尝试添加 BrowserTransferStateModule ( https://www.twilio.com/blog/faster-javascript-web-apps-angular-universal-transferstate-api-watchdog ),但这也不起作用。

app.module.ts

import {BrowserModule} from '@angular/platform-browser';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {TransferHttpCacheModule} from "@nguniversal/common";

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  imports: [
    BrowserModule.withServerTransition({appId: 'serverApp'}),
    TransferHttpCacheModule, // <-
    ...
    HttpClientModule
  ]
  bootstrap: [AppComponent]
})
export class AppModule {
}

app.server.module.ts

import {NgModule} from '@angular/core';
import {ServerModule, ServerTransferStateModule} from '@angular/platform-server';

import {AppModule} from './app.module';
import {AppComponent} from './app.component';
import {ModuleMapLoaderModule} from '@nguniversal/module-map-ngfactory-loader';

@NgModule({
  imports: [
    AppModule,
    ServerModule,
    ModuleMapLoaderModule,
    ServerTransferStateModule // <-
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule {
}

ma​​in.ts

document.addEventListener('DOMContentLoaded', () => {
  platformBrowserDynamic()
    .bootstrapModule(AppModule)
  .catch(err => console.error(err));
});

我的 API 服务 api.service.ts

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from "rxjs";

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  private API_URL = '/api/';

  constructor(private http: HttpClient) {
  }

  public get<T>(url: string): Observable<T> {
    return this.http.get<T>(this.API_URL + url);
  }

  public post<T>(url: string, payload: T): Observable<T> {
    return this.http.post<T>(this.API_URL + url, payload);
  }

  ...

}

HTTP 调用 home.component.ts

import {Component, OnInit} from '@angular/core';
import {ApiService} from "../../api.service";
import {Offer} from "../../offer-preview/offer.model";

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.sass']
})
export class HomeOffersComponent implements OnInit {
  latestOffers: Offer[];

  constructor(private apiService: ApiService) {
  }

  ngOnInit() {
    this.apiService.get<Offer[]>("offer")
      .subscribe(data => this.latestOffers = data);
  }

}

根据官方 TransferHttpCacheModule 文档,浏览器不应向 /api/offer 生成 XHR,但我在 Developer Network Tools 中看到了 XHR 调用。

我做错了什么?我错过了什么吗?

最佳答案

这是因为 TransferHttpCacheModule 之间的绝对 URL 不匹配用作每个请求的缓存键。 例如:

<表类="s-表"> <头> <日> 服务器 客户端 <正文> baseUrl 本地主机:4200 域名.com 资源 /api/人 /api/人 绝对网址 http://localhost:4200/api/people https://example.com/api/people

只有当两个绝对 URL 相同时,请求才会被成功缓存。 为了避免这个缺点,您可以通过 BrowserTransferStateModule 实现自己的缓存。和拦截器,例如如所述here .

请务必只使用相对 URL:

const url = new URL(req.url);
const rel = url.toString().substring(url.origin.length);
this.transferState.set(makeStateKey(rel), event.body);

关于node.js - TransferHttpCacheModule 不会阻止 Angular 8 中的重复 HTTP 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57187758/

相关文章:

node.js - multer,multiparty和connect-multiparty + Nodejs之间的区别

javascript - 参数 'myController' 不是函数,未定义

c# - 在 vscode 中使用 Angular 4 调试 Asp.Net Core 应用程序

javascript - 从 setTimeout() 返回一个值

angular - 动态添加元标记 - Angular

JavaScript 对象实例委托(delegate)/转发

node.js - 无法从 0.12.13 更新 sails 1.0.1

node.js - zeromq.js-等待连接

node.js - 如何在 Angular Universal 中配置缓存

Angular 8 Universal Build 在 SCSS 导入时失败