NestJS部署AWS Lambda后依赖注入失效,HttpService/AiManagerService为undefined
NestJS部署AWS Lambda后依赖注入失效问题排查与解决
我正在开发一个基于设备、食材和限制列表生成食谱的项目,使用NestJS结合Axios发起HTTP请求。本地运行完全正常,但通过AWS CDK部署到Lambda后,日志显示依赖注入的AiManagerService、HttpService均为undefined,报错信息为TypeError: Cannot read properties of undefined (reading 'buildRecipe')。
核心代码片段
AppModule
@Module({ imports: [AiManagerModule, HttpModule.register({}),], controllers: [AppController], providers: [AppService], }) export class AppModule { }
自定义模块AiManagerModule
@Module({ controllers: [AiManagerController], providers: [AiManagerService], imports: [HttpModule] }) export class AiManagerModule { }
自定义控制器AiManagerController
@Controller('ai-manager') export class AiManagerController { constructor(private readonly service: AiManagerService) { // AWS日志中this.service为undefined,本地正常 console.log('AiManagerController constructor HttpService: ', this.service); } @Post('create-recipe') async generate( @Body() body: CreateRecipesRequestBody, ): Promise<BaseResponseBody<RecipeResponseBody[]>> { console.log('create recipe body', body); // AWS日志中this.service为undefined,本地正常 console.log('create recipe service', this.service); let ingredients = body.ingredientList; let equipements = body.equipmentList; let restrictions = body.restrictionList; //报错行 let result = await this.service.buildRecipe( 'pt-br', ingredients, equipements, restrictions, false, ); console.log('create recipe result', result); return BaseResponseBody.success(result); } }
自定义服务AiManagerService
@Injectable() export class AiManagerService { constructor(private readonly service: HttpService) { // AWS日志中this.service为undefined,本地正常 console.log('AiManagerService constructor HttpService: ', this.service); } async buildRecipe( lang: string, ingredients: string[], equipements: string[], restrictions?: string[], shouldAddOptionals?: boolean, ): Promise<RecipeResponseBody[]> { //通过prompt发起axios请求等逻辑... } }
tsconfig.json
{ "compilerOptions": { "module": "commonjs", "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "allowSyntheticDefaultImports": true, "target": "ES2023", "sourceMap": true, "outDir": "./dist", "baseUrl": "./", "incremental": true, "skipLibCheck": true, "strictNullChecks": true, "forceConsistentCasingInFileNames": true, "noImplicitAny": false, "strictBindCallApply": false, "noFallthroughCasesInSwitch": false } }
Lambda配置(CDK)
const nestJsLambda = new NodejsFunction(this, 'LAMBDANAMEHERE', { runtime: lambda.Runtime.NODEJS_22_X, memorySize: 512, timeout: cdk.Duration.seconds(10), handler: 'handler', entry: entryFile, projectRoot: simpleAppRoot, depsLockFilePath: lockFilePath, bundling: { minify: false, externalModules: [ '@nestjs/microservices', '@nestjs/websockets/socket-module', ], nodeModules: [ '@nestjs/common', '@nestjs/axios', 'axios' ], environment: { NODE_ENV: 'production', } }, environment: { }, });
已做排查
- 多次检查依赖注入,服务已添加
@Injectable注解,模块导入正确 - 本地运行完全正常
- 尝试调整Lambda配置中
nodeModules列表,无效 cdk synth和cdk deploy无警告或错误
解决方案
1. 修正Lambda入口文件的NestJS初始化逻辑
确保Lambda入口通过NestJS的Express适配器正确初始化应用上下文,避免直接导出控制器方法导致依赖注入失效。示例入口代码:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { Handler, Context } from 'aws-lambda'; import { ExpressAdapter } from '@nestjs/platform-express'; import * as express from 'express'; let cachedServer: Handler; export const handler: Handler = async (event: any, context: Context) => { if (!cachedServer) { const expressApp = express(); const adapter = new ExpressAdapter(expressApp); const app = await NestFactory.create(AppModule, adapter); app.enableCors(); await app.init(); cachedServer = expressApp; } return cachedServer(event, context); };
2. 调整CDK打包配置,禁用树摇并优化依赖处理
Lambda打包时的树摇机制可能会移除NestJS依赖注入所需的装饰器元数据,修改打包配置:
bundling: { minify: false, treeShake: false, // 禁用树摇,保留元数据 externalModules: [ '@nestjs/microservices', '@nestjs/websockets/socket-module', ], // 移除手动指定nodeModules的配置,让CDK自动处理所有依赖,避免遗漏元数据相关依赖 environment: { NODE_ENV: 'production', } },
3. 明确指定tsconfig文件路径
在CDK配置中明确指定tsconfig路径,确保打包时应用正确的装饰器元数据编译选项:
const nestJsLambda = new NodejsFunction(this, 'LAMBDANAMEHERE', { // ...其他配置 tsconfig: './tsconfig.json', });
4. 验证依赖版本兼容性
确认@nestjs/core、@nestjs/axios、aws-cdk-lib等依赖版本相互兼容,使用npm ci确保部署环境与本地依赖版本完全一致,避免因版本不匹配导致的反射元数据丢失。
5. 避免直接引用控制器/服务实例
确保Lambda入口不直接引用控制器或服务的方法,必须通过NestJS应用上下文获取实例,否则依赖注入容器无法正常初始化依赖。
内容的提问来源于stack exchange,提问作者Marcelo Esser
相关产品推荐
相关产品推荐

