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

Apollo项目中前后端重复定义typeDefs的冗余问题如何优化?

核心认知澄清

首先要明确:你提到的两处定义根本不是同一种东西,不存在“冗余”的前提:

  • 服务端schema.js里的typeDefs是服务端对外暴露的全量接口契约,定义了服务端支持的所有类型、字段、参数、返回值规则,用来做请求校验、解析器绑定、权限校验,是服务端能力的全集。
  • 客户端typeDefs.ts里写的gql语句是当前组件的按需查询声明,只需要声明当前组件用到的字段即可,这是GraphQL相比REST“要什么拿什么”的核心设计,你如果硬要复用服务端全量Schema做查询,反而会每次请求拉取所有无用字段,彻底丢掉GraphQL的优势,还可能引发数据越权问题。

如果你的诉求是减少手动同步Schema的成本、避免客户端查询写错字段、自动生成类型,可以用下面的成熟方案优化:

优化方案1:使用GraphQL代码生成工具自动同步类型与查询封装

这是生产环境的标准实践,完全不需要手动复制服务端Schema到客户端:

  1. 你的Apollo Server启动后,默认会在/graphql端点对外暴露标准的SDL格式全量Schema
  2. 引入GraphQL Code Generator工具,直接拉取服务端运行时的Schema,扫描你在客户端写的零散gql查询语句,自动生成:
    • 全类型安全的useQuery/useMutation自定义Hook,不需要你手动封装
    • 所有查询参数、返回值的TS类型定义
    • 编译阶段自动校验客户端查询的字段是否和服务端Schema匹配,字段名写错、传参不对直接报错,不需要等运行时才发现问题

基础配置示例,安装对应依赖后在项目根目录新建codegen.ts:

import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'http://localhost:4000/graphql', // 直接读取本地运行的服务端Schema,无需手动复制文件
  documents: ['src/**/*.{ts,tsx}'], // 扫描客户端代码里写的gql查询片段
  generates: {
    './src/generated/': {
      preset: 'client',
      plugins: [],
    }
  }
};
export default config;

配置完成后跑生成命令,就可以直接在组件里导入生成的Hook使用,所有类型自动推导,完全不需要手动维护两边的定义同步。

优化方案2:Monorepo架构下抽离公共Schema模块

如果你的前后端代码放在同一个Monorepo仓库中,可以把服务端的Schema定义抽离到独立的公共workspace包中:

  • 服务端直接从公共包导入typeDefs,传入ApolloServer完成初始化
  • 客户端仅在做本地Mock、客户端缓存Schema配置的时候导入公共Schema,绝对不要直接用全量Schema发起查询
    注意:不要直接从服务端代码目录往前端项目里导入文件,否则打包工具会把express、apollo-server-express等Node端依赖打进前端bundle,直接引发打包报错。

现有代码的问题修正

你贴的客户端代码存在一个明显的路径引用错误:MyComponent里导入的路径是../../server/typedefs,但服务端的Schema文件实际名为schema.js,客户端自己写的查询文件是typeDefs.ts,两者不要混淆,直接跨前后端目录导入代码的行为本身就不符合工程规范。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:33:25