首页/文章/nextjs

使用NestJS开发小程序后台

2024-09-10
14685 分钟
...

前言

前一篇写NestJS的特点,使用NestJS,开启我们的Hello World! 以及NestJS各种热更新方法,本篇会写NestJS在实际项目中的应用。(ORM、参数校验、全局错误处理等等)

NestJS 中使用 TypeORM

一、安装依赖

npm install @nestjs/typeorm typeorm mysql2

这里假设使用 MySQL 数据库,你可以根据实际情况选择其他数据库驱动。

二、配置数据库连接

  1. 在项目根目录下创建一个文件 ormconfig.js,内容如下:
module.exports = {
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: 'your_username',
    password: 'your_password',
    database: 'your_database_name',
    entities: [__dirname + '/**/*.entity{.ts,.js}'],
    synchronize: true, 
};

将 your_usernameyour_password 和 your_database_name 替换为你的实际数据库连接信息。

  1. 在 main.ts 文件中引入并配置 TypeORM:

  import { NestFactory } from '@nestjs/core';
  import { AppModule } from './app.module';
  import { TypeOrmModule } from '@nestjs/typeorm';

  async function bootstrap() {
     const app = await NestFactory.create(AppModule);
     app.useGlobalPipes();

     await app.listen(3000);
   }

  bootstrap();

三、创建实体

在 src/entities 目录下创建一个实体文件,例如 user.entity.ts

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; 

@Entity() 
export class User { 
    @PrimaryGeneratedColumn() 
    id: number; 
    @Column() 
    name: string; 
    @Column() 
    email: string; 
}

四、创建数据访问层(Repository)

在 src/repositories 目录下创建一个文件,例如 user.repository.ts

import { Repository } from 'typeorm'; 
import { User } from '../entities/user.entity'; 
export class UserRepository extends Repository<User> {}

五、在模块中配置 TypeORM 和使用数据访问层

在对应的模块文件中,例如 app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserEntity } from './entities/user.entity';
import { UserRepository } from './repositories/user.repository';
import { UsersService } from './services/users.service';
import { UsersController } from './controllers/users.controller';

@Module({
  imports: [TypeOrmModule.forFeature([UserEntity])],
  providers: [UsersService, UserRepository],
  controllers: [UsersController],
})
export class AppModule {}

六、使用数据访问层进行数据库操作

在服务文件中注入数据访问层并进行数据库操作,例如在 users.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UserRepository } from './repositories/user.repository';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(UserRepository)
    private readonly userRepository: UserRepository,
  ) {}

  async findAll(): Promise<User[]> {
    return this.userRepository.find();
  }

  async create(user: User): Promise<User> {
    return this.userRepository.save(user);
  }
}

这样就可以在 NestJS 项目中使用 TypeORM 进行数据库操作了。

NestJS中全局错误处理

一、创建全局错误过滤器

  1. 创建一个类来实现ExceptionFilter接口,用于处理全局错误。例如,创建一个文件global-exception.filter.ts
   import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
   import { Request, Response } from 'express';

   @Catch()
   export class GlobalExceptionFilter implements ExceptionFilter {
     catch(exception: any, host: ArgumentsHost) {
       const ctx = host.switchToHttp();
       const response = ctx.getResponse<Response>();
       const request = ctx.getRequest<Request>();
       const status = exception instanceof HttpException? exception.getStatus() : 500;
       const message =
         exception instanceof HttpException
          ? exception.getResponse()['message'] || exception.message
           : 'Internal server error';

       response.status(status).json({
         statusCode: status,
         message,
         timestamp: new Date().toISOString(),
         path: request.url,
       });
     }
   }

这个过滤器会捕获所有的异常,并返回一个统一格式的错误响应。

二、注册全局错误过滤器

  1. main.ts文件中注册全局错误过滤器:
   import { NestFactory } from '@nestjs/core';
   import { AppModule } from './app.module';
   import { GlobalExceptionFilter } from './global-exception.filter';

   async function bootstrap() {
     const app = await NestFactory.create(AppModule);
     app.useGlobalFilters(new GlobalExceptionFilter());
     await app.listen(3000);
   }

   bootstrap();

现在,所有在应用程序中抛出的异常都会被全局错误过滤器捕获,并返回统一格式的错误响应。你可以根据实际需求进一步扩展错误处理逻辑,例如记录错误日志、发送通知等。

错误日志

在 NestJS 中可以添加错误日志来记录应用程序中的错误信息,以便于调试和故障排查。以下是一种添加错误日志的方法:

一、安装日志库

可以使用winstonwinston-daily-rotate-file库来实现日志记录。

npm install winston winston-daily-rotate-file

二、创建日志服务

创建一个日志服务来处理日志记录。例如,创建一个文件logger.service.ts

import { Injectable, LoggerService as NestLoggerService } from '@nestjs/common';
import * as winston from 'winston';
import 'winston-daily-rotate-file';

@Injectable()
export class LoggerService implements NestLoggerService {
  private logger: winston.Logger;

  constructor() {
    this.logger = winston.createLogger({
      level: 'info',
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.json(),
      ),
      transports: [
        new winston.transports.Console(),
        new winston.transports.DailyRotateFile({
          filename: 'logs/application-%DATE%.log',
          datePattern: 'YYYY-MM-DD',
          zippedArchive: true,
          maxSize: '20m',
          maxFiles: '14d',
        }),
      ],
    });
  }

  log(message: string) {
    this.logger.info(message);
  }

  error(message: string, trace: string) {
    this.logger.error({ message, trace });
  }

  warn(message: string) {
    this.logger.warn(message);
  }

  debug(message: string) {
    this.logger.debug(message);
  }

三、在全局错误过滤器中使用日志服务

修改全局错误过滤器,在捕获到错误时使用日志服务记录错误信息。文件global-exception.filter.ts

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
import { LoggerService } from './logger.service';

@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {
  constructor(private readonly logger: LoggerService) {}

  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception instanceof HttpException? exception.getStatus() : 500;
    const message =
      exception instanceof HttpException
       ? exception.getResponse()['message'] || exception.message
        : 'Internal server error';

    this.logger.error({
      statusCode: status,
      message,
      timestamp: new Date().toISOString(),
      path: request.url,
    });

    response.status(status).json({
      statusCode: status,
      message,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

在 main.ts 中注册全局错误过滤器和日志服务:

   import { NestFactory } from '@nestjs/core';
   import { AppModule } from './app.module';
   import { GlobalExceptionFilter } from './global-exception.filter';
   import { LoggerService } from './logger.service';

   async function bootstrap() {
     const app = await NestFactory.create(AppModule);
     app.useGlobalFilters(new GlobalExceptionFilter(app.get(LoggerService)));
     await app.listen(3000);
   }

   bootstrap();

四、在其他地方使用日志服务

可以在其他服务、控制器等地方注入日志服务,并使用它来记录日志信息。例如,在一个服务中:

import { Injectable } from '@nestjs/common';
import { LoggerService } from './logger.service';

@Injectable()
export class SomeService {
  constructor(private readonly logger: LoggerService) {}

  someMethod() {
    this.logger.log('This is a log message.');
    
    try {
      
    } catch (error) {
      this.logger.error('An error occurred in someMethod', error.stack);
    }
  }
}

这样,在应用程序中发生错误时,错误信息会被记录到日志文件中,同时也可以在其他地方使用日志服务记录各种信息,方便调试和故障排查。

NestJS参数校验 zod

因为之前koa用的Joi,想找一个类似的。zod 是一个强大的类型安全和数据验证库。 优点:

  • 提供了简洁直观的 API 来定义和验证数据结构。
  • 支持类型推导,使得类型安全更加可靠。

Joizod都是 JavaScript 和 TypeScript 中常用的用于数据验证和校验的库,它们有一些相似之处,但也存在一些不同点:

一、相似之处

  1. 数据验证功能

    • 两者都可以对输入数据进行各种类型的验证,包括字符串长度、数值范围、数据格式(如电子邮件地址)等。
    • 例如,都可以验证一个字符串是否为有效的电子邮件地址,或者一个数值是否在特定的范围内。
  2. 链式调用语法

    • Joizod都提供了一种链式调用的语法,使得可以方便地组合多个验证规则。
    • 例如,可以通过连续调用方法来添加多个验证条件,使代码更加清晰和易读。
import { z } from 'zod';

const userSchema = z.object({
  name: z.string().min(3),
  email: z.string().email(),
});

export class CreateUserDto {
  constructor(data: z.infer<typeof userSchema>) {
    Object.assign(this, data);
  }

  name: string;
  email: string;
}
  1. 安装 zod 库:
   npm install zod
  1. 创建数据验证 schema:

    例如,创建一个用于用户创建的 schema:

   import { z } from 'zod';

   const createUserSchema = z.object({
     name: z.string().min(3),
     email: z.string().email(),
   });
  1. 在控制器中使用:
   import { Controller, Post, Body } from '@nestjs/common';
   import { createUserSchema } from './schemas/user.schema';

   @Controller('users')
   export class UserController {
     @Post()
     async createUser(@Body() body: any) {
       const parsedData = createUserSchema.safeParse(body);
       if (!parsedData.success) {
         
         return { error: parsedData.error };
       }
       
       const { name, email } = parsedData.data;
       
       return { message: 'User created successfully' };
     }
   }

这样,当有 POST 请求到 /users 路径时,会使用 zod schema 对请求体进行校验,如果校验不通过,会返回校验错误信息。

后面把koa项目使用Nestjs重构完,就把代码开源。

参考:

nest.nodejs.cn

cloud.tencent.com/developer/a…

blog.csdn.net/weixin_4712…

cloud.tencent.com/developer/a…

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
nextjs2026-04-03
揭秘 Next.js 的图像魔法
揭秘 Next.js 的“图像魔法”:不仅仅是自动压缩 你可能以为 组件只是帮你把图片体积变小了,但实际上,它更像是一个 实时的图像处理引擎 。当你把一张高清大图扔给它时,Next.js 会在服务器端(或构建时)根据用户的设备情况,动态生成最合适的图片版本。 这背后主要依赖以下几个核心机制: 现代格式的自动转码 这是性能提升最显著的一点。你上传的可能是兼容性最好的 JPG 或 PNG,但 Next.js 会检测访问者浏览器的能力。 We...
学习
nextjs2024-12-31
Next.js App Router 项目,想加个进度条,但是怎么监听页面跳转
问题起因是我想给自己博客页面切换时加一个进度条。博客前端技术栈是 React,使用 Next 做了 SSR。在进度条方面,npm 上有非常成熟的库 。我们只需要调用 和 即可开启和结束进度条。我们监听到页面开始、结束切换的时候,调用 和 即可。但是问题是,Next 13 版本以后推出的 App Router 模式并没有给出监听路由切换的 API。 先来看看 Pages Router 模式的做法: 可以发现,在 npm 上面有一个 Nex...
学习
nextjs2024-10-09
NextJs从0-1实现一个博客系统
Nextjs 是什么 是一个基于 React 的开源框架,用于构建生产级别的 React 应用程序。它为开发人员提供了一套丰富的工具和约定,使得创建高性能、可扩展的 Web 应用程序变得更加容易。 相关代码 Next.js 的主要特性: 服务器端渲染 (SSR): 静态站点生成 (SSG): API 路由: 文件系统路由: 图像优化: TypeScript 支持: 自定义服务器: 插件系统: 安装 使用官网推荐的方式安装,执行 ,输入项...
学习
nextjs2024-09-18
Nextjs首屏加载速度性能从80分优化到98分
google控制台的网络network去看首次加载资源请求是否有重复加载的情况 google控制台的performance来录制首屏加载过程的文件时长以及阻塞情况,避免一些首次加载无须展示的组件的优化 \ 打包size优化,@next/bundle analyzer可视化的检查页面和打包的资源大小,然后针对性去优化 选择性能指标检测工具我用的 更好的了解真实用户的体验 以上是对性能可视化和测试的工具,方便针对性优化 首先对图片,css进...
学习
nextjs2024-09-14
NextJs 14 从入门到精通
node 环境 npx、yarn、bun 工具皆可(个人偏好 ,因为它快) 初始化 next 项目 项目目录 安装 autoprefixer 及配置 postcss 从 Layout 开始 app/layout.tsx 是整个应用的主布局文件,相当于React的main.ts或App.tsx,它主要做以下几个事情: 项目 metadata 加载全局样式 globals.css 加载网络/本地字体 定义应用顶级布局 国际化 i18n 第三...
学习
nextjs2024-05-14
Next.js 跨域问题的各种解法
本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究! 前言 跨域是使用 Next.js 常遇到的问题,问题主要分为两类: 1. 如何调用一个跨域接口? 2. 如何实现一个跨域接口? 本篇我们会先从跨域的基础知识开始讲起,然后讲解 Next.js 下这两大类问题的各种解决方案,帮你系统解决跨域问题!快收藏、点赞这篇文章留做备忘吧! PS:系统学习 Next.js,欢迎入手小册 。基础篇、实战篇、源码篇...
学习

评论

请登录后发表评论

去登录
加载评论中...

目录