NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架,支持模块化架构、装饰器模式和依赖注入等特性。本文将详细介绍如何安装Node.js和Nest CLI,创建并配置第一个Nest项目。此外,文章还将深入探讨nest后端开发中的控制器与服务、数据库集成以及测试和调试技巧。
Nest框架简介 基本概念和特点NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。其主要特点包括:
- 模块化架构:NestJS 的核心理念是模块化,每个模块都是一个自包含的单元,可以独立开发和测试。
- 装饰器模式:NestJS 支持 TypeScript 装饰器,这使得代码更加简洁和可维护。
- 依赖注入:通过依赖注入,可以轻松地管理对象之间的依赖关系,提高代码的可测试性和可维护性。
- 可插拔中间件:类似 Express 的中间件机制,可以轻松地添加或移除中间件。
- 高性能:基于高性能的 Node.js 平台和框架设计,NestJS 旨在提供最佳的性能表现。
NestJS 可以与多种数据库集成,常见的包括 MySQL、MongoDB 和 PostgreSQL。选择数据库时需要考虑具体需求,如数据量、查询性能和开发复杂度。本文以 MongoDB 为例进行介绍。
安装Node.js和Nest CLI安装Node.js
-
访问 Node.js官网,下载并安装最新版本的 Node.js。
- 验证安装成功:
node -v npm -v
安装Nest CLI
Nest CLI 是一个命令行工具,用于创建和管理 NestJS 项目。安装步骤如下:
-
安装 Nest CLI:
npm install -g @nestjs/cli
- 验证安装成功:
nest -v
-
创建一个新的 Nest 项目:
nest new my-nest-app
-
进入项目目录:
cd my-nest-app
-
启动开发服务器:
npm run start:dev
- 访问
http://localhost:3000
,你应该能看到默认的 "Hello World!" 页面。
NestJS 的项目结构通常包含以下几个主要文件和目录:
src/
:主要的源代码目录。app.module.ts
:应用的主模块文件。app.controller.ts
:应用的主控制器文件。app.service.ts
:应用的服务文件。main.ts
:应用的主入口文件。
package.json
:项目配置文件,包含依赖、脚本等信息。tsconfig.json
:TypeScript 编译配置文件。nest-cli.json
:Nest CLI 配置文件。
控制器用于处理 HTTP 请求并返回响应。控制器可以通过装饰器 @Controller()
定义。
创建控制器
nest generate controller app
-
创建控制器:
// src/app.controller.ts import { Controller, Get, Post, Body } from '@nestjs/common'; import { AppService } from './app.service'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() getHello(): string { return this.appService.getHello(); } @Post('/create') create(@Body() body: any) { return this.appService.create(body); } }
-
创建服务:
// src/app.service.ts export class AppService { getHello(): string { return 'Hello World!'; } create(body: any) { return `Created: ${JSON.stringify(body)}`; } }
环境变量在开发和生产环境中非常重要,用于区分不同的环境配置。NestJS 支持通过环境变量来配置不同环境的设置。
-
创建
.env
文件,用于存储环境变量:# .env PORT=3000 DATABASE_URL=mongodb://localhost:27017/mydb
-
在
src/app.module.ts
中使用环境变量:// src/app.module.ts import { Module } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ ConfigModule.forRoot({ envFilePath: '.env', isGlobal: true, }), ], }) export class AppModule {}
-
在其他模块或服务中访问环境变量:
import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; @Injectable() export class MyService { constructor(private readonly configService: ConfigService) {} getDatabaseUrl() { return this.configService.get<string>('DATABASE_URL'); } }
-
安装依赖:
npm install express @nestjs/microservices
-
在
src/app.module.ts
中引入和配置:import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { HttpModule } from '@nestjs/axios'; import { MicroserviceOptions, Transport } from '@nestjs/microservices'; @Module({ imports: [ HttpModule, // 配置微服务 { name: 'UserModule', module: UserModule, useFactory: (configService: ConfigService) => ({ transport: Transport.REDIS, options: { url: configService.get<string>('REDIS_URL'), }, }), inject: [ConfigService], }, ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
控制器用于处理 HTTP 请求并返回响应。控制器可以通过装饰器 @Controller()
定义。
创建控制器
nest generate controller user
-
创建控制器:
// src/user.controller.ts import { Controller, Get, Post, Body } from '@nestjs/common'; import { UserService } from './user.service'; @Controller('users') export class UserController { constructor(private readonly userService: UserService) {} @Get() getUsers() { return this.userService.getAllUsers(); } @Post() createUser(@Body() user: any) { return this.userService.createUser(user); } }
-
创建服务:
// src/user.service.ts import { Injectable } from '@nestjs/common'; @Injectable() export class UserService { private users = []; getAllUsers() { return this.users; } createUser(user: any) { this.users.push(user); return `User created: ${JSON.stringify(user)}`; } }
-
配置模块:
// src/user.module.ts import { Module } from '@nestjs/common'; import { UserController } from './user.controller'; import { UserService } from './user.service'; @Module({ controllers: [UserController], providers: [UserService], }) export class UserModule {}
创建控制器方法
// src/user.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { UserService } from './user.service';
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get()
getUsers() {
return this.userService.getAllUsers();
}
@Post()
createUser(@Body() user: any) {
return this.userService.createUser(user);
}
}
创建服务方法
// src/user.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {
private users = [];
getAllUsers() {
return this.users;
}
createUser(user: any) {
this.users.push(user);
return `User created: ${JSON.stringify(user)}`;
}
}
配置模块
// src/user.module.ts
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
@Module({
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
服务的创建和使用
服务通常用于处理异步操作、数据访问以及其他业务逻辑。服务可以通过依赖注入的方式注入到控制器或其他服务中。
-
创建服务类:
// src/user.service.ts import { Injectable } from '@nestjs/common'; @Injectable() export class UserService { private users = []; getAllUsers() { return this.users; } createUser(user: any) { this.users.push(user); return `User created: ${JSON.stringify(user)}`; } updateUser(id: string, user: any) { return this.findUserById(id).then((u) => { u.name = user.name; u.email = user.email; return u; }); } deleteUser(id: string) { return this.findUserById(id).then((u) => { const index = this.users.indexOf(u); if (index > -1) { this.users.splice(index, 1); } return true; }); } findUserById(id: string) { return this.users.find((user) => user.id === id); } }
-
在控制器中使用服务:
// src/user.controller.ts import { Controller, Get, Post, Body, Put, Param } from '@nestjs/common'; import { UserService } from './user.service'; @Controller('users') export class UserController { constructor(private readonly userService: UserService) {} @Get() getUsers() { return this.userService.getAllUsers(); } @Post() createUser(@Body() user: any) { return this.userService.createUser(user); } @Put(':id') updateUser(@Param('id') id: string, @Body() user: any) { return this.userService.updateUser(id, user); } @Delete(':id') deleteUser(@Param('id') id: string) { return this.userService.deleteUser(id); } }
-
配置模块:
// src/user.module.ts import { Module } from '@nestjs/common'; import { UserController } from './user.controller'; import { UserService } from './user.service'; @Module({ controllers: [UserController], providers: [UserService], }) export class UserModule {}
NestJS 可以与多种数据库集成,常见的包括 MySQL、MongoDB 和 PostgreSQL。选择数据库时需要考虑具体需求,如数据量、查询性能和开发复杂度。本文以 MongoDB 为例进行介绍。
连接数据库并集成到Nest项目-
安装 MongoDB 客户端:
npm install @nestjs/mongoose mongoose
-
配置 MongoDB 客户端:
// src/app.module.ts import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [ MongooseModule.forRoot(process.env.DATABASE_URL), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
-
创建模型:
// src/user.schema.ts import { Schema, Document } from 'mongoose'; import { Prop, Schema as SchemaDecorator } from '@nestjs/mongoose'; @SchemaDecorator() export class UserSchema extends Document { @Prop({ required: true }) name: string; @Prop({ required: true }) email: string; } export const UserSchemaName = 'User'; export const UserSchemaObject = UserSchema; export const UserSchemaModelName = 'User';
-
创建服务:
// src/user.service.ts import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { UserSchema } from './user.schema'; import { Model } from 'mongoose'; @Injectable() export class UserService { constructor(@InjectModel(UserSchema.name) private userModel: Model<UserSchema>) {} async createUser(user: UserSchema) { return this.userModel.create(user); } async getAllUsers() { return this.userModel.find().exec(); } async updateUser(id: string, user: UserSchema) { return this.userModel.findByIdAndUpdate(id, user, { new: true }).exec(); } async deleteUser(id: string) { return this.userModel.findByIdAndRemove(id).exec(); } }
-
创建控制器方法:
// src/user.controller.ts import { Controller, Get, Post, Body, Put, Param } from '@nestjs/common'; import { UserService } from './user.service'; @Controller('users') export class UserController { constructor(private readonly userService: UserService) {} @Get() getAllUsers() { return this.userService.getAllUsers(); } @Post() createUser(@Body() user: any) { return this.userService.createUser(user); } @Put(':id') updateUser(@Param('id') id: string, @Body() user: any) { return this.userService.updateUser(id, user); } @Delete(':id') deleteUser(@Param('id') id: string) { return this.userService.deleteUser(id); } }
-
更新用户信息:
// src/user.service.ts async updateUser(id: string, user: UserSchema) { return this.userModel.findByIdAndUpdate(id, user, { new: true }).exec(); }
-
删除用户:
// src/user.service.ts async deleteUser(id: string) { return this.userModel.findByIdAndRemove(id).exec(); }
-
在控制器中添加更新和删除方法:
// src/user.controller.ts @Put(':id') updateUser(@Param('id') id: string, @Body() user: any) { return this.userService.updateUser(id, user); } @Delete(':id') deleteUser(@Param('id') id: string) { return this.userService.deleteUser(id); }
Jest 是一个流行的 JavaScript 测试框架,可以用来编写单元测试。
-
安装 Jest:
npm install --save-dev jest @types/jest ts-jest
-
在
jest.config.js
中配置 Jest:// jest.config.js module.exports = { preset: 'ts-jest', testEnvironment: 'node', };
-
创建测试文件:
// src/user.service.spec.ts import { UserService } from './user.service'; import { UserSchema } from './user.schema'; describe('UserService', () => { let userService: UserService; beforeEach(() => { userService = new UserService(); }); it('should create user', async () => { const user = new UserSchema({ name: 'John Doe', email: 'john.doe@example.com', }); const result = await userService.createUser(user); expect(result).toBe('User created'); }); it('should get all users', async () => { const users = await userService.getAllUsers(); expect(users.length).toBe(0); }); });
- 运行测试:
npm run test
Supertest 是一个用于测试 HTTP API 的库。
-
安装 Supertest:
npm install --save-dev supertest
-
创建集成测试文件:
// src/user.controller.spec.ts import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import { UserController } from './user.controller'; import { UserService } from './user.service'; import { AppModule } from '../../app.module'; import { request } from 'supertest'; import { join } from 'path'; describe('UserController (e2e)', () => { let app: INestApplication; beforeEach(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); it('/users (GET)', () => { return request(app.getHttpServer()) .get('/users') .expect(200) .expect([]); }); it('/users (POST)', () => { return request(app.getHttpServer()) .post('/users') .send({ name: 'John Doe', email: 'john.doe@example.com' }) .expect(201) .expect('User created'); }); });
- 运行测试:
npm run test
调试是开发过程中不可或缺的一部分。NestJS 提供了一些内置的调试工具和技巧。
-
使用断点调试:
// src/user.service.ts import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { UserSchema } from './user.schema'; import { Model } from 'mongoose'; @Injectable() export class UserService { constructor(@InjectModel(UserSchema.name) private userModel: Model<UserSchema>) {} async createUser(user: UserSchema) { debugger; return this.userModel.create(user); } }
-
使用
console.log
打印调试信息:// src/user.service.ts @Injectable() export class UserService { async createUser(user: UserSchema) { console.log('Creating user:', user); return this.userModel.create(user); } }
-
使用环境变量区分调试和生产环境:
// .env DEBUG=true
-
通过环境变量启用调试模式:
// src/app.module.ts import { Module } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ ConfigModule.forRoot({ envFilePath: '.env', isGlobal: true, }), ], }) export class AppModule {}
-
在主入口文件中启用调试模式:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { ConfigService } from '@nestjs/config'; async function bootstrap() { const app = await NestFactory.create(AppModule); const configService = app.get(ConfigService); if (configService.get<string>('DEBUG')) { app.enableShutdownHooks(); } await app.listen(3000); } bootstrap();
-
打包应用:
npm run build
- 使用 PM2 进行部署:
npm install pm2 -g pm2 start dist/main.js --name my-nest-app
PM2 是一个进程管理器,可以帮助我们管理 Node.js 应用的生命周期。
-
安装 PM2:
npm install pm2 -g
-
使用 PM2 启动应用:
pm2 start dist/main.js --name my-nest-app
-
保存应用配置:
pm2 save
- 重启应用:
pm2 restart all
-
获取 SSL 证书:
可以使用 Let's Encrypt 提供的免费 SSL 证书。-
安装 Certbot:
sudo apt-get install certbot -y
- 生成 SSL 证书:
sudo certbot --nginx -d example.com -d www.example.com
-
-
配置反向代理(使用 Nginx 为例):
-
安装 Nginx:
sudo apt-get install nginx -y
-
编辑 Nginx 配置文件:
server { listen 80; server_name example.com www.example.com; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; } } server { listen 443 ssl; server_name example.com www.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; } }
- 重启 Nginx:
sudo systemctl restart nginx
-
通过以上步骤,你就可以成功部署和管理一个 NestJS 应用,并确保其在生产环境中运行良好。
共同学习,写下你的评论
评论加载中...
作者其他优质文章