NestJS中GraphQL响应缓存不生效问题排查与解决
问题
我在NestJS中使用GraphQL,已完成基础开发并尝试添加缓存功能,配置了apollo-server-plugin-response-cache插件及@cacheControl指令,但缓存未生效。相关配置代码如下,请问问题出在哪?如何解决?是否与包版本有关?
配置代码:
import responseCachePlugin from 'apollo-server-plugin-response-cache'; @Module({ imports: [ GraphQLModule.forRoot({ driver: ApolloFederationDriver, autoSchemaFile: { federation: 2, }, plugins: [responseCachePlugin({})], buildSchemaOptions: { directives: [ new GraphQLDirective({ name: 'cacheControl', locations: [ DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT, DirectiveLocation.INTERFACE, DirectiveLocation.UNION, DirectiveLocation.QUERY, DirectiveLocation.FIELD, ], args: { maxAge: { type: GraphQLInt }, scope: { type: new GraphQLEnumType({ name: 'CacheControlScope', values: { PUBLIC: { value: 'PUBLIC' }, PRIVATE: { value: 'PRIVATE' }, }, }), }, inheritMaxAge: { type: GraphQLBoolean }, }, }), ], }, }), ], providers: [xResolver, xService], }) export class xModule {}
期望使用方式:
import { Directive, Query, Resolver } from '@nestjs/graphql'; import { userType } from './dto/create-user.input'; import { X } from './entities/x.entity'; import { XService } from './x.service'; @Resolver(() => X) export class xResolver { constructor(private readonly xService: XService) {} @Query(() => userType) @Directive('@cacheControl(maxAge: 30)') async user() { return this.xService.getUser(); } }
问题分析与解决
1. 手动定义cacheControl指令引发冲突
NestJS的GraphQL模块已经内置了cacheControl指令的官方实现,你手动通过GraphQLDirective创建的指令会和内置版本冲突,导致缓存插件无法正确识别配置规则。
解决:直接删除buildSchemaOptions.directives中的手动cacheControl配置,修改后的GraphQLModule配置如下:
import responseCachePlugin from 'apollo-server-plugin-response-cache'; @Module({ imports: [ GraphQLModule.forRoot({ driver: ApolloFederationDriver, autoSchemaFile: { federation: 2, }, plugins: [responseCachePlugin({})], // 移除原有的buildSchemaOptions.directives配置 }), ], providers: [xResolver, xService], }) export class xModule {}
2. 包版本兼容性问题
缓存失效大概率和版本不匹配有关,需确保以下依赖版本对齐:
@nestjs/apollo和apollo-server-plugin-response-cache需使用兼容的大版本:- 若
@nestjs/apollo是^12.x,则apollo-server-plugin-response-cache对应^3.x - 若
@nestjs/apollo是^11.x,则插件对应^2.x
- 若
- 如果你用Apollo Federation v2,
@apollo/federation的版本也要和上述包版本兼容
检查方法:查看package.json中的依赖版本,执行npm list @nestjs/apollo apollo-server-plugin-response-cache确认版本是否匹配。
3. 缓存插件的必要配置补充
默认的内存缓存在测试场景下可用,但如果自定义了请求上下文(context),需要确保cacheControl相关信息能被插件获取。另外,可通过配置sessionId区分私有/公共缓存:
plugins: [ responseCachePlugin({ // 基于请求头的authorization区分用户私有缓存,不需要可省略 sessionId: (ctx) => ctx.request.http.headers.get('authorization') || null, }), ],
4. 正确验证缓存是否生效
不要只靠响应时间判断,建议通过以下方式验证:
- 查看响应头的
Cache-Control字段,确认是否包含max-age=30 - 在Resolver的
user方法中添加日志,观察多次请求是否只执行一次方法逻辑 - 启用Apollo Server日志,查看是否有
Cache HIT/Cache MISS的日志标记
内容的提问来源于stack exchange,提问作者Matin
相关产品推荐
相关产品推荐

