AWS CDK项目使用graphql-code-generator报模块未找到错误
AWS CDK TypeScript Lambda项目GraphQL Code Generator模块未找到问题排查
问题背景
在AWS CDK TypeScript Lambda项目中使用GraphQL Code Generator生成GraphQL相关代码,优先选用更现代的typed-document-node插件,备选typescript-document-nodes插件,但启用这两个插件时均抛出模块未找到错误,仅typescript-operations插件可正常生成符合预期的代码。
现有配置
codegen.yml配置
watch: false watchConfig: usePolling: false interval: 1000 overwrite: true schema: - xxxxxxxxx: headers: 'x-api-key': xxxxxx - "awsAppsyncDirectives.graphql" documents: - 'src/graphql/*.query.graphql' - 'src/graphql/*.fragment.graphql' - 'src/graphql/*/*.query.graphql' - 'src/graphql/*/*.fragment.graphql' generates: src/@types/graphql.ts: plugins: - "typescript" - "typescript-operations" - "typescript-document-nodes" - "typed-document-node"
tsconfig.json配置
{ "compilerOptions": { "target": "ES2021", "module": "commonjs", "moduleResolution": "node", "lib": [ "ES2021", "DOM" ], "esModuleInterop": true, "declaration": true, "strict": true, "noImplicitAny": false, "noImplicitThis": false, "strictNullChecks": true, "alwaysStrict": true, "noUnusedLocals": false, "noUnusedParameters": false, "noImplicitReturns": true, "noFallthroughCasesInSwitch": false, "inlineSourceMap": true, "inlineSources": true, "experimentalDecorators": true, "strictPropertyInitialization": false, "useUnknownInCatchVariables": false, "typeRoots": [ "./node_modules/@types", "./src/@types" ] }, "include": [ "./src/lambda", "./src/layers/helper/nodejs/node_modules" ], "exclude": [ "node_modules", "cdk.out" ] }
错误表现
typed-document-node插件错误
生成的graphql.ts文件在编辑器中提示模块缺失,执行codegen cli做代码生成时也抛出相同TS编译错误:
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; Cannot find module '@graphql-typed-document-node/core' or its corresponding type declarations.
CLI执行时的错误日志:
[12:26:05 PM] File change detected. Starting incremental compilation... src/@types/graphql.ts:1:51 - error TS2307: Cannot find module '@graphql-typed-document-node/core' or its corresponding type declarations. 1 import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; [12:26:05 PM] Found 1 error. Watching for file changes.
typescript-document-nodes插件错误
该插件本身可正常生成代码,生成的文档节点片段示例:
export const ListAuthorizationTwinfields = gql` query listAuthorizationTwinfields($filter: ModelAuthorizationTwinfieldFilterInput) { listAuthorizationTwinfields(filter: $filter) { items { accessToken accessTokenValidatedUntil active administrationId cluster createdAt debtorsImported debtorsStarted firstBankStatement id incremental invoicesImported invoicesStarted lastExecutedCallback memosImportedAt memosStartedAt officeCode officeName refreshToken transactionCodes transactionsStarted transactionsImported updatedAt } } } `;
在Lambda函数中按如下方式引用生成内容时:
import { ListAuthorizationTwinfields } from "../../@types/graphql"; data = await graphql.query({ query: ListAuthorizationTwinfields, variables: variables }, graphqlConfig);
运行时抛出错误:Cannot find module '../../@types/graphql'。
经测试验证:从graphql.ts中引入生成的TypeScript类型可正常工作,仅引入gql格式的文档节点时触发模块找不到错误。
根因分析与修复方案
两个错误均为配置缺失/错误导致,无框架兼容问题:
1. typed-document-node模块找不到问题
根因:codegen的插件仅负责生成代码逻辑,生成代码中引用的@graphql-typed-document-node/core属于运行时依赖,未被安装到项目中。
修复步骤:
- 执行安装命令补全依赖:
npm install @graphql-typed-document-node/core graphql - 注意
graphql是该包的peer依赖,版本要求>=15.0.0,必须同步安装。
2. typescript-document-nodes引用运行时报错问题
根因:tsconfig配置存在两处逻辑错误:
include配置仅覆盖了./src/lambda和lambda层路径,src/@types目录未被纳入TS编译范围,该目录下包含运行时代码(gql文档节点)的graphql.ts不会被编译输出为js文件,运行时自然找不到对应模块。typeRoots配置错误:当前配置将./src/@types设为类型根目录,TS会默认该目录下所有文件都是全局类型声明,不会编译其中的运行时代码,这也是为什么引入纯类型可以正常工作、引入运行时值(gql节点)就报错的核心原因。
修复步骤:- 修改tsconfig的
include配置,将./src/@types纳入编译范围:"include": [ "./src/lambda", "./src/@types", "./src/layers/helper/nodejs/node_modules" ] - 调整
typeRoots配置,移除./src/@types项。如果需要存放自定义全局类型,可单独新建src/types/global目录存放.d.ts声明文件,不要把包含运行时代码的生成文件放在typeRoots指定的目录下。 - 补全缺失依赖:
typescript-document-nodes生成的代码使用了gql标签,该标签来自graphql-tag包,需执行安装命令:npm install graphql-tag
优化建议
- 不需要同时启用
typescript-document-nodes和typed-document-node两个插件,优先选用typed-document-node即可,它不需要额外依赖graphql-tag,类型推断更精准,打包体积更小。 - 生成的代码文件建议不要放在
@types目录下,@types是全局类型声明的约定目录,可将生成路径改为src/generated/graphql.ts,从根源上避免和TS类型解析规则冲突。
内容的提问来源于stack exchange,提问作者Gerhard
相关产品推荐
相关产品推荐

