基于Serverless框架实现Monorepo NestJS多AWS Lambda部署与API网关集成
NestJS Monorepo + Serverless + AWS Lambda 架构实现方案
一、Monorepo 目录结构规划
先明确代码库的分层结构,确保模块隔离与共享代码复用:
your-monorepo/ ├── packages/ │ ├── auth/ # Auth 模块(独立 Lambda) │ │ ├── src/ │ │ ├── serverless.yml │ │ └── tsconfig.json │ ├── users/ # Users 模块(独立 Lambda) │ │ ├── src/ │ │ ├── serverless.yml │ │ └── tsconfig.json │ ├── posts/ # Posts 模块(独立 Lambda) │ │ ├── src/ │ │ ├── serverless.yml │ │ └── tsconfig.json │ └── shared/ # 全局共享代码库 │ ├── src/ │ │ ├── dto/ │ │ ├── guards/ │ │ └── utils/ │ └── package.json ├── serverless-compose.yml # 根编排配置 ├── package.json └── tsconfig.base.json
二、Serverless 配置结构
采用 serverless-compose 统一管理多模块部署,同时绑定到同一个 API 网关:
1. 根编排配置(serverless-compose.yml)
负责创建统一 API 网关,并传递网关参数给各个业务模块:
services: auth: path: packages/auth params: apiGatewayId: ${shared.apiGatewayId} apiGatewayStage: ${shared.apiGatewayStage} users: path: packages/users params: apiGatewayId: ${shared.apiGatewayId} apiGatewayStage: ${shared.apiGatewayStage} posts: path: packages/posts params: apiGatewayId: ${shared.apiGatewayId} apiGatewayStage: ${shared.apiGatewayStage} shared: apiGatewayId: !Ref ApiGateway apiGatewayStage: prod resources: Resources: ApiGateway: Type: AWS::ApiGateway::RestApi Properties: Name: MonorepoUnifiedAPI Description: Single entrypoint for all NestJS module endpoints ApiGatewayStage: Type: AWS::ApiGateway::Stage Properties: RestApiId: !Ref ApiGateway StageName: prod DeploymentId: !Ref ApiGatewayDeployment ApiGatewayDeployment: Type: AWS::ApiGateway::Deployment Properties: RestApiId: !Ref ApiGateway DependsOn: - AuthLambdaPermission - UsersLambdaPermission - PostsLambdaPermission
2. 单个模块配置(以 auth/serverless.yml 为例)
每个业务模块独立定义 Lambda 函数,并绑定到统一 API 网关的指定路径:
service: auth-service frameworkVersion: '3' provider: name: aws runtime: nodejs18.x region: us-east-1 environment: NODE_ENV: production functions: authHandler: handler: dist/main.handler events: - httpApi: path: /auth/{proxy+} method: any apiId: ${param:apiGatewayId} stage: ${param:apiGatewayStage} package: patterns: - '!node_modules/**' - 'dist/**' plugins: - '@nestjs/serverless'
三、共享代码高效管理
1. 工作区配置(根 package.json)
使用 npm/pnpm 工作区实现共享包的本地依赖:
{ "name": "monorepo-root", "private": true, "workspaces": [ "packages/*" ], "scripts": { "build:all": "npm run build --workspaces", "deploy:all": "serverless deploy --config serverless-compose.yml" } }
2. 模块依赖共享包
在 auth/users/posts 等模块的 package.json 中添加共享包依赖:
{ "name": "auth-service", "dependencies": { "@your-monorepo/shared": "*", "@nestjs/common": "^10.0.0", // 其他业务依赖 } }
3. TypeScript 路径映射(tsconfig.base.json)
避免相对路径混乱,统一导入共享代码:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@your-monorepo/shared/*": ["packages/shared/src/*"] }, "module": "commonjs", "target": "ES2021", "strict": true, "esModuleInterop": true } }
每个业务模块的 tsconfig.json 继承根配置:
{ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }
四、API 网关多 Lambda 集成建议
- 路径前缀隔离模块:用
/auth/*、/users/*、/posts/*作为各模块的路由前缀,清晰区分业务边界,避免路由冲突。 - 统一网关认证:在 API 网关层面配置自定义授权器(复用 Auth 模块的认证函数),所有请求先经过授权校验,无需每个模块重复实现认证逻辑。
- 跨模块调用优化:Lambda 之间调用优先用 EventBridge 做事件驱动,避免硬耦合;若需同步调用,使用 AWS SDK 的
Lambda.invoke,并做好超时与错误处理。 - 统一响应格式:在 API 网关配置响应模板,将 Lambda 返回的错误/结果转换为标准格式(如
{ "code": 200, "data": {}, "msg": "" }),减少前端适配成本。 - 冷启动优化:将
@nestjs/*、aws-sdk等公共依赖打包成 Lambda 层,所有业务模块共享该层,减小单个 Lambda 包体积,加快冷启动速度。
五、NestJS 适配 Lambda 示例
每个模块的 main.ts 需生成兼容 Lambda 的 handler:
import { NestFactory } from '@nestjs/core'; import { ExpressAdapter } from '@nestjs/platform-express'; import { AppModule } from './app.module'; import { serverlessExpress } from '@vendia/serverless-express'; import express from 'express'; // 缓存服务实例,减少冷启动 let cachedServer; export const handler = async (event, context) => { if (!cachedServer) { const expressApp = express(); const adapter = new ExpressAdapter(expressApp); const app = await NestFactory.create(AppModule, adapter); app.enableCors(); await app.init(); cachedServer = serverlessExpress({ app: expressApp }); } return cachedServer(event, context); };
内容的提问来源于stack exchange,提问作者jusimen
相关产品推荐
相关产品推荐

