RedwoodJS GraphQL `File` 标量配置指南:禁用默认 `File` 标量以自定义类型
2026/9/21 15:40:47 网站建设 项目流程
  • 后端
  • 前端
  • Web框架
  • 开发工具

【免费下载链接】redwood

RedwoodGraphQL

项目地址:https://gitcode.com/gh_mirrors/re/redwood
点击查看免费下载

导读

本文围绕 RedwoodJS 中 GraphQL Schema 默认注入的File标量展开,说明它从 v8.0.0 起被自动加入 schema 所带来的命名冲突问题,以及通过 changeset .changesets/11540.md 引入的可关闭机制。读完本文你将掌握:如何在redwood.tomlapi/src/functions/graphql.ts两处协同配置、该开关在源码中的完整生效链路(从项目配置解析到 schema 组装再到类型生成),以及禁用后自定义File标量或移除它的注意事项。

背景:v8.0.0 起默认注入的File标量

RedwoodJS 从 v8.0.0 开始,会在生成的 GraphQL schema 中默认加入一个File标量。这样做的好处是开箱即用地支持文件上传等场景;但副作用是:如果应用想要自己定义同名File标量,就会与框架默认注入的标量发生命名冲突,导致 schema 合并失败或语义被覆盖。

changeset .changesets/11540.md 正是为解决这一问题而引入:它允许开发者关闭默认注入File标量的行为,把 schema 的标量空间完全交还给应用。

从源码可以看到,框架的默认标量分为两类:

  • 不可关闭的通用标量BigIntDateTimeDateTimeJSONJSONObjectByte,定义在 packages/graphql-server/src/rootSchema.ts 的 root schema 中,始终注入;
  • 可配置的扩展标量:目前仅有File,单独抽离在scalarSchemas对象中(见 packages/graphql-server/src/rootSchema.ts),其注入与否由配置开关控制。
// packages/graphql-server/src/rootSchema.ts export const scalarSchemas = { File: gql` scalar File `, } export type ScalarSchemaKeys = keyof typeof scalarSchemas

这种设计使得框架内置标量分为「always-on」与「opt-out」两种治理模型,为后续扩展更多可配置标量预留了结构。

配置方式一:redwood.toml中的graphql.includeScalars

关闭默认File标量需要在两个地方同时配置。首先是在项目根目录的redwood.toml中:

[graphql] includeScalars.File = false

配置项的类型与默认值

该配置项在 packages/project-config/src/config.ts 中被建模为graphql.includeScalars: { File: boolean },其默认值是{ File: true }(见 packages/project-config/src/config.ts):

graphql: { fragments: false, trustedDocuments: false, includeScalars: { File: true }, },

也就是说:不写任何配置时,File标量默认包含;只有显式设置为false才会排除。这一「默认包含、显式排除」的语义同样被记录在GraphQLYogaOptions.includeScalars的类型注释中(见 packages/graphql-server/src/types.ts):

The default is to include. You must set tofalseto exclude.

在运行时,getConfig()会解析redwood.toml并合并上述默认值,最终得到完整的graphql.includeScalars结构。配置测试(packages/project-config/src/tests/config.test.ts)也覆盖了该字段的解析行为。

配置方式二:api/src/functions/graphql.ts中的includeScalars选项

第二处配置位于 API 侧的 GraphQL 处理器入口api/src/functions/graphql.ts。在该文件的createGraphQLHandler调用中传入includeScalars选项:

export const handler = createGraphQLHandler({ authDecoder, getCurrentUser, loggerConfig: { logger, options: {} }, directives, sdls, services, onException: () => { // Disconnect from your database with an unhandled exception. db.$disconnect() }, // highlight-start includeScalars: { File: false, }, // highlight-end })

为什么两处都要配置?

  • redwood.toml中的配置服务于构建期与代码生成期:SDK 需要据此判断是否把File标量写入生成的 schema 与类型定义(详见下文「生成链路」);
  • graphql.ts中的配置服务于运行时 schema 组装createGraphQLHandler会把该值一路透传给makeMergedSchema,决定最终暴露给客户端的 schema 中是否包含File标量。

两处不一致会导致「生成的类型定义里有File、但运行时 schema 没有」或反之的漂移,因此官方文档明确要求两处同步配置。includeScalars选项的类型为RedwoodScalarConfig(见 packages/graphql-server/src/types.ts):

export interface RedwoodScalarConfig { File?: boolean }

其注释同样提醒:该选项应与redwood.toml中的graphql.includeScalars保持一致。

底层原理:File标量注入的完整链路

1. 运行时 schema 组装:makeMergedSchema

运行时是否注入File标量,最终由 packages/graphql-server/src/makeMergedSchema.ts 决定。核心逻辑如下:

export const makeMergedSchema = ({ sdls, services, schemaOptions = {}, directives, subscriptions = [], includeScalars, }: { // ... includeScalars?: RedwoodScalarConfig // ... }) => { const sdlSchemas = Object.values(sdls).map(({ schema }) => schema) const rootEntries = [rootGqlSchema.schema] // We cannot access the getConfig from project-config here so the user must supply it via a config option if (includeScalars?.File !== false) { rootEntries.push(rootGqlSchema.scalarSchemas.File) } const typeDefs = mergeTypes([ ...rootEntries, ...directives.map((directive) => directive.schema), ...subscriptions.map((subscription) => subscription.schema), ...sdlSchemas, ], { all: true }) // ... }

关键点:

  • includeScalars?.File !== false的判定意味着只有显式传入false才排除undefinedtrue都会保留File标量;
  • 源码注释明确指出「无法在此处访问 project-config 的 getConfig,因此必须由调用方通过配置选项传入」——这正是要求你在graphql.ts中手写includeScalars的原因;
  • makeMergedSchema的调用链为createGraphQLHandlercreateGraphQLYoga(packages/graphql-server/src/createGraphQLYoga.ts)→makeMergedSchemaincludeScalars在每一层都被透传。

2. 生成期链路:schema 文件与 TS 类型

redwood.toml中的开关同时影响yarn rw generate types等命令产出的文件:

  • schema 生成:packages/internal/src/generate/graphqlSchema.ts 遍历rootSchema.scalarSchemas,仅当redwoodProjectConfig.graphql.includeScalars[name]为真时才把该标量加入 schema 指针映射:
for (const [name, schema] of Object.entries(rootSchema.scalarSchemas)) { if (redwoodProjectConfig.graphql.includeScalars[name as ScalarSchemaKeys]) { schemaPointerMap[print(schema)] = {} } }
  • TS 类型生成:packages/internal/src/generate/graphqlCodeGen.ts 中,只有config.graphql.includeScalars.File为真时,才会把File映射为File类型,否则不生成对应映射:
const config = getConfig() if (config.graphql.includeScalars.File) { scalars.File = 'File' }

对应的快照测试(packages/internal/src/tests/snapshots/graphqlSchema.test.ts.snap)确认默认情况下生成的 schema 中包含scalar File;配置测试(packages/internal/src/tests/clientPreset.test.ts)则以includeScalars: { File: true }为前提验证客户端预设的生成行为。

3. 关闭后会发生什么

当两处配置都设为File: false后:

  1. 运行时合并的 schema 中不再包含scalar File定义,应用可以自由地在自己的 SDL 中声明同名File标量(或依赖其他库提供),不会再与框架默认标量冲突;
  2. 生成的schema.graphql与 TS 类型定义中同样不再出现File标量,保证开发期类型与运行时行为一致;
  3. 若应用既不自定义File标量、又关闭了默认注入,则在 SDL 中引用File会导致 schema 校验失败——关闭操作应当与「自行定义或继续不使用」二选一配套进行。

自定义File标量:冲突解决后的落地方式

关闭默认注入后,即可按 RedwoodJS 自定义标量的常规流程注册自己的File标量。相关文档位于 docs/docs/graphql.md 的Custom Scalars一节(含Scalars vs Service vs Directives的选型对比)。基本思路是:

  1. api/src下定义 SDL 与对应的 resolver,声明scalar File
  2. 通过createGraphQLHandlerschemaOptions或 SDL 配套 resolver 注册其序列化/反序列化逻辑;
  3. 保持redwood.tomlgraphql.ts两处includeScalars.File = false的同步配置。

提示:默认注入的File标量仅提供scalar File的类型声明(见rootSchema.tsscalarSchemas),其语义对应标准的File类型。自定义实现时需自行补齐解析、序列化与校验逻辑。

小结

  • File标量自 v8.0.0 起默认注入 schema,可能导致与自定义File标量命名冲突;
  • 关闭方式为「双配置」:redwood.toml[graphql] includeScalars.File = false+graphql.tsincludeScalars: { File: false }
  • 默认值为{ File: true },只有显式false才排除;运行时判定逻辑为includeScalars?.File !== false(makeMergedSchema.ts);
  • 该开关同时作用于运行时 schema 组装、生成期 schema 文件与 TS 类型三个层面,两处配置必须保持一致,否则会出现类型与运行时 schema 的漂移;
  • 关闭后即可自由自定义File标量,或直接移除该类型。

如果你想深入了解 RedwoodJS 其他内置标量(DateTimeJSON等的映射行为)或自定义标量的完整写法,可继续阅读 docs/docs/graphql.md 的Custom Scalars章节,以及 packages/graphql-server/src/rootSchema.ts 中的默认标量声明。

  • 后端
  • 前端
  • Web框架
  • 开发工具

【免费下载链接】redwood

RedwoodGraphQL

项目地址:https://gitcode.com/gh_mirrors/re/redwood
点击查看免费下载
上一篇:如何让10美元鼠标好用过触控板:Mac Mouse Fix零基础完整上手
下一篇:多格式兼容Renovate:格式自适应

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询