跳到主要内容

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

方式一:控制台部署

  1. 打开 CloudBase 控制台 访问 腾讯云 CloudBase 控制台

  2. 创建 HTTP 云函数

    • 函数类型:选择「HTTP 云函数」
    • 函数名称:输入 nest-app(或自定义名称)
    • 提交方法:选择「本地上传文件夹」
  3. 上传代码

    • 函数代码:选择您的 NestJS 项目根目录
    • 运行环境:选择 Node.js 18.15(推荐)或其他支持版本
    • 自动安装依赖:开启
  4. 完成部署 点击「创建」按钮,等待部署完成

方式二: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 的云原生能力,可以帮助您快速构建高质量的企业级应用。

建议在实际项目中根据业务需求进一步优化应用架构、添加数据库集成、实现身份认证等功能。