NestJS
NestJS 是一个基于 TypeScript/Node.js 的企业级后端框架,采用模块化设计,融合了 OOP(面向对象编程)、FP(函数式编程)和微服务架构。它底层支持 Express/Fastify,提供依赖注入、装饰器路由、GraphQL 集成等特性,适合构建高效、可维护的服务器端应用,尤其契合全栈 TypeScript 开发。
本指南将详细介绍如何在 CloudBase HTTP 云函数上开发和部署 NestJS 应用程序。
前提条件
在开始之前,请确保您已具备以下条件:
- Node.js 环境:版本 16.13 或更高(推荐 18.15+)
- npm 或 yarn:包管理工具
- NestJS CLI:全局安装 NestJS 命令行工具
- CloudBase 账号:已注册腾讯云账号并开通云开发服务
环境准备
1. 安装 NestJS CLI
# 全局安装 NestJS CLI
npm install -g @nestjs/cli
# 验证安装
nest --version
2. 创建 NestJS 应用
如果您已有 NestJS 应用,可以跳过此步骤。
# 创建新的 NestJS 应用
nest new nest-cloudbase-app
# 进入项目目录
cd nest-cloudbase-app
选择包管理器(推荐使用 npm):
? Which package manager would you ❤️ to use? (Use arrow keys)
❯ npm
yarn
pnpm
应用开发
1. 项目结构
创建完成后,您将得到以下项目结构:
nest-cloudbase-app/
├── src/
│ ├── app.controller.ts # 应用控制器
│ ├── app.module.ts # 应用模块
│ ├── app.service.ts # 应用服务
│ └── main.ts # 应用入口文件
├── test/ # 测试文件
├── package.json
├── tsconfig.json
└── nest-cli.json
2. 修改应用入口文件
编辑 src/main.ts 文件,配置端口为 9000(CloudBase HTTP 云函数要求):
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 启用 CORS
app.enableCors({
origin: true,
credentials: true,
});
// CloudBase HTTP 云函数要求使用 9000 端口
const port = process.env.PORT || 9000;
await app.listen(port, '0.0.0.0');
console.log(`Application is running on: http://localhost:${port}`);
}
bootstrap();
3. 创建示例 API
创建用户模块
# 生成用户模块
nest generate module users
nest generate controller users
nest generate service users
编辑用户控制器
编辑 src/users/users.controller.ts:
import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
import { UsersService } from './users.service';
export interface User {
id: number;
name: string;
email: string;
}
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll(): User[] {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string): User {
return this.usersService.findOne(+id);
}
@Post()
create(@Body() user: Omit<User, 'id'>): User {
return this.usersService.create(user);
}
@Put(':id')
update(@Param('id') id: string, @Body() user: Partial<User>): User {
return this.usersService.update(+id, user);
}
@Delete(':id')
remove(@Param('id') id: string): { message: string } {
this.usersService.remove(+id);
return { message: `User ${id} deleted successfully` };
}
}
编辑用户服务
编辑 src/users/users.service.ts:
import { Injectable, NotFoundException } from '@nestjs/common';
export interface User {
id: number;
name: string;
email: string;
}
@Injectable()
export class UsersService {
private users: User[] = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' },
];
findAll(): User[] {
return this.users;
}
findOne(id: number): User {
const user = this.users.find(user => user.id === id);
if (!user) {
throw new NotFoundException(`User with ID ${id} not found`);
}
return user;
}
create(userData: Omit<User, 'id'>): User {
const newUser: User = {
id: Math.max(...this.users.map(u => u.id), 0) + 1,
...userData,
};
this.users.push(newUser);
return newUser;
}
update(id: number, userData: Partial<User>): User {
const userIndex = this.users.findIndex(user => user.id === id);
if (userIndex === -1) {
throw new NotFoundException(`User with ID ${id} not found`);
}
this.users[userIndex] = { ...this.users[userIndex], ...userData };
return this.users[userIndex];
}
remove(id: number): void {
const userIndex = this.users.findIndex(user => user.id === id);
if (userIndex === -1) {
throw new NotFoundException(`User with ID ${id} not found`);
}
this.users.splice(userIndex, 1);
}
}
4. 添加健康检查端点
编辑 src/app.controller.ts:
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
@Get('health')
getHealth(): { status: string; timestamp: string } {
return {
status: 'ok',
timestamp: new Date().toISOString(),
};
}
}
本地测试
1. 启动开发服务器
# 开发模式启动
npm run start:dev
# 或者生产模式启动
npm run build
npm run start:prod
2. 测试 API 端点
使用 curl 或 Postman 测试应用:
# 健康检查
curl http://localhost:9000/health
# 获取所有用户
curl http://localhost:9000/users
# 获取单个用户
curl http://localhost:9000/users/1
# 创建新用户
curl -X POST http://localhost:9000/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice Johnson","email":"alice@example.com"}'
# 更新用户
curl -X PUT http://localhost:9000/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"John Updated","email":"john.updated@example.com"}'
# 删除用户
curl -X DELETE http://localhost:9000/users/1
部署配置
1. 创建 scf_bootstrap 文件
在项目根目录创建 scf_bootstrap 文件(无扩展名):
#!/bin/sh
# 设置端口为 9000(CloudBase HTTP 云函数要求)
export PORT=9000
# 启动 NestJS 应用
npm run start:prod
2. 设置文件权限
chmod +x scf_bootstrap
3. 优化 package.json
确保 package.json 包含正确的启动脚本:
{
"scripts": {
"build": "nest build",
"start": "node dist/main",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main"
}
}
4. 创建 .gitignore
# 依赖
node_modules/
# 构建输出
dist/
build/
# 日志
*.log
npm-debug.log*
# 环境变量
.env
.env.local
.env.*.local
# IDE
.vscode/
.idea/
# 操作系统
.DS_Store
Thumbs.db
部署到 CloudBase
方式一:控制台部署
打开 CloudBase 控制台 访问 腾讯云 CloudBase 控制台
创建 HTTP 云函数
- 函数类型:选择「HTTP 云函数」
- 函数名称:输入
nest-app(或自定义名称) - 提交方法:选择「本地上传文件夹」
上传代码
- 函数代码:选择您的 NestJS 项目根目录
- 运行环境:选择
Node.js 18.15(推荐)或其他支持版本 - 自动安装依赖:开启
完成部署 点击「创建」按钮,等待部署完成
方式二:CLI 部署(敬请期待)
访问应用
部署成功后,您可以参考通过 HTTP 访问云函数设置自定义域名访问HTTP 云函数。
您可以测试以下接口:
- 根路径:
/- Express 欢迎页面 - 健康检查:
/health- 查看应用状态
最佳实践
1. 环境变量管理
在 CloudBase 控制台配置环境变量:
// src/config/database.config.ts
export const databaseConfig = {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT) || 3306,
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'nestjs_app',
};
2. 日志配置
// src/main.ts
import { Logger } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
logger: ['error', 'warn', 'log'],
});
const logger = new Logger('Bootstrap');
// ... 其他配置
await app.listen(port, '0.0.0.0');
logger.log(`Application is running on port ${port}`);
}
3. 全局异常处理
// src/filters/http-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
message: exception.message,
});
}
}
4. 数据验证
# 安装验证相关包
npm install class-validator class-transformer
// src/users/dto/create-user.dto.ts
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
export class CreateUserDto {
@IsNotEmpty()
@IsString()
name: string;
@IsEmail()
email: string;
}
常见问题
Q: 部署后访问 404 错误?
A: 检查以下几点:
- 确认
scf_bootstrap文件存在且有执行权限 - 验证端口配置为 9000
- 检查应用是否正确构建(
npm run build)
Q: 应用启动失败?
A: 常见原因:
- Node.js 版本不兼容,建议使用 18.15+
- 依赖安装失败,检查
package.json配置 - 内存不足,考虑优化代码或升级函数配置
Q: 如何查看应用日志?
A: 在 CloudBase 控制台的「云函数」→「函数详情」→「日志」中查看运行日志。
Q: 如何连接数据库?
A: 推荐使用 CloudBase 数据库或其他云数据库服务:
// 安装数据库相关包
npm install @nestjs/typeorm typeorm mysql2
// 配置数据库连接
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
autoLoadEntities: true,
synchronize: process.env.NODE_ENV !== 'production',
}),
],
})
export class AppModule {}
总结
通过本指南,您已经学会了如何在 CloudBase HTTP 云函数上开发和部署 NestJS 应用。NestJS 的模块化架构和强大的功能特性,结合 CloudBase 的云原生能力,可以帮助您快速构建高质量的企业级应用。
建议在实际项目中根据业务需求进一步优化应用架构、添加数据库集成、实现身份认证等功能。