You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular SSR集成GraphQL与Apollo时TransferState状态无法传递到客户端

Angular SSR中TransferState结合Apollo GraphQL失效的解决方案

问题根源分析

  1. 客户端读取TransferState时未将结果赋值给业务变量,导致无法复用服务端数据
  2. Apollo查询结果结构处理错误:Apollo的query响应包含data字段,直接断言为数组会导致数据异常
  3. 未同步Apollo的SSR缓存与TransferState,单纯使用TransferState无法阻止Apollo客户端重复发起请求

修正步骤

1. 修复组件内TransferState与Apollo查询逻辑

调整ngOnInit中的代码,正确处理Apollo查询结果,并确保客户端读取TransferState后赋值给业务变量:

async ngOnInit() {
  const myTransferStateKey = makeStateKey<any>('myDatas');

  if (this.transferState.hasKey(myTransferStateKey)) {
    console.log('HomeComponent ngOnInit hasKey');
    // 关键:将读取到的服务端数据赋值给posts
    this.posts = this.transferState.get(myTransferStateKey, []);
    this.transferState.remove(myTransferStateKey);
  } else {
    console.log('HomeComponent ngOnInit noKey');
    // 正确解析Apollo查询响应的data字段
    const response = await this.graphql.query({ query: this.home_query }).toPromise();
    // 根据你的GraphQL查询结构调整data后的字段名(示例为posts)
    this.posts = response.data.posts as {
      capital: string;
      currency: string;
      languages: [];
      name: string;
      native: string;
    }[];
    this.transferState.set(myTransferStateKey, this.posts);
  }
}

2. 同步Apollo缓存与TransferState

为了彻底避免Apollo客户端重复请求,需要在服务端将Apollo缓存写入TransferState,客户端启动时从TransferState恢复缓存:

服务端Apollo配置

import { ModuleMapLoaderModule, TransferState } from '@angular/platform-server';
import { ApolloModule, APOLLO_OPTIONS } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { InMemoryCache } from '@apollo/client/core';
import { makeStateKey } from '@angular/core';

export function createApollo(httpLink: HttpLink, transferState: TransferState) {
  const cache = new InMemoryCache();
  const stateKey = makeStateKey<any>('apollo-state');

  // 服务端渲染完成后,将Apollo缓存序列化到TransferState
  transferState.onSerialize(stateKey, () => cache.extract());

  return {
    link: httpLink.create({ uri: '/graphql' }),
    cache,
  };
}

@NgModule({
  imports: [ApolloModule, ModuleMapLoaderModule],
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink, TransferState],
    },
  ],
})
export class ServerApolloModule {}

客户端Apollo配置

import { ApolloModule, APOLLO_OPTIONS } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { InMemoryCache } from '@apollo/client/core';
import { TransferState, makeStateKey } from '@angular/core';

export function createApollo(httpLink: HttpLink, transferState: TransferState) {
  const stateKey = makeStateKey<any>('apollo-state');
  const cache = new InMemoryCache();

  // 从TransferState读取服务端缓存并恢复到Apollo
  const serverCache = transferState.get(stateKey, null);
  if (serverCache) {
    cache.restore(serverCache);
  }

  return {
    link: httpLink.create({ uri: '/graphql' }),
    cache,
  };
}

@NgModule({
  imports: [ApolloModule],
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink, TransferState],
    },
  ],
})
export class ClientApolloModule {}

3. 配置Apollo查询的缓存策略

在查询时设置fetchPolicy: 'cache-first',让Apollo优先读取缓存,进一步避免重复请求:

const response = await this.graphql.query({
  query: this.home_query,
  fetchPolicy: 'cache-first'
}).toPromise();

内容的提问来源于stack exchange,提问作者Redberry57

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 22:25:18