Nest.js 是一个现代的企业级 Node.js web 框架,在最近使用 Nest.js 实践一些项目的总结了一些使用心得,但也从中学到了很多东西,在这里总结下来和大家分享。
1. API 设置全局前缀
为 API 设置一个全局前缀可以区分接口版本,如通常会用 /api/v1
作为的 API 端点的前缀。
为什么我们需要前缀? 好的 API 在设计时要考虑到向后的兼容性。当增强或增加一个 API 时,我们应该确保已经线上使用到该 API的业务不受影响。”简而言之,API 前缀是为了向后兼容。
2. 模块划分
Nest.js 是以模块化结构为基础的,服务端应用应该按功能职现被划分为几个部分,通常情况下,将你的目录结构应该按模块划分而不是按类型分成文件夹。
以下是按类型划分文件夹(不推荐)
以下是按模块划分文件夹(推荐)
对于 Nest.js,模块是一个包含 .module.ts
文件的文件夹,其中包含一个 @Module({})
装饰器。但并非每个文件夹都需要有一个 .module.ts
文件。 例如,你可以创建一个文件夹名为 utils
来存储你的工具函数或 JSON 文件。
通过将文件组织到模块文件夹中,会变得清晰,并且可以避免很多错误。 此外,如果你不遵守此原则,Nest.js 可能会在构建过程中崩溃。
3.使用 DTOs
DTO = 数据传输对象。 Dtos 就像接口,目标是传输数据并验证它,主要用于路由器/控制器。
你可以通过使用它们来简化 API 主体和查询验证逻辑。 例如,下面的 AuthDto 自动将用户电子邮件和密码映射到对象 DTO 以强制验证。
上面的例子是期望密码超过 5 个字符,你可以将 dtos 与 class-validator 包配对以自动抛出错误。
4. 应该使用 Data Mapper/Repository 模式,而不是 Active Record
如果你正在使用 PostgreSQL 或 MySQL 等关系数据库,那么请使用 TypeOrm,它是 Typescript 最强大的 ORM 之一。
TypeOrm 可以使用两种模式,一种是由 ruby on rails 推广的活动记录模式,另一种是使用存储库的数据映射器模式。
使用 Active Record 方法,可以在模型本身内定义所有查询方法,并使用模型方法保存、删除和加载对象。 下面是使用 Active Record 模式的样子:
const user = new UserEntity();
user.name = "Vladimir";
user.job = "programmer";
await user.save();
使用 Data Mapper 方法,你可以在称为“存储库”的单独类中定义所有查询方法,并使用存储库保存、删除和加载对象:
const user = this.userRepository.create();
user.name = "Vladimir";
user.job = "programmer";
await this.userRepository.save(user);
虽然活动记录乍一看似乎更好,但它违背了 Nest.js 提供的模块化,因为活动记录与全局实体一起工作,而数据映射器需要在使用它们之前将实体注入每个模块。
数据映射器可能看起来有点冗长,但它是中/大型项目的更好解决方案。 它也非常适合测试,因为它适用于依赖注入!
5. 应该使用相对路径,而不是绝对路径
你可以使用绝对路径或相对路径导入 es6 模块。 但在 Nest.js 在开发中使用绝对路径,再构建应用时它会崩溃。
// relative imports
import { SecurityService } from '../security/security.service';
import { CommentService } from '../comment/comment.service';
// absolute imports
import { SecurityService } from 'src/security/security.service';
import { CommentService } from 'src/comment/comment.service';
6. 使用 Exclude 来隐藏不必要的数据
使用过滤器从数据库中获取的数据是很常见的。过滤器的整个目标是删除或格式化来自数据库的数据。 这会导致很多垃圾逻辑,使代码变得更冗余。如果是需要隐藏某些字段,可以使用@Exclude() 装饰器。
import { Exclude } from 'class-transformer';
export class UserEntity {
id: number;
firstName: string;
lastName: string;
@Exclude()
password: string;
constructor(partial: Partial<UserEntity>) {
Object.assign(this, partial);
}
}
7. 使用实体的 getter 方法
一些通用的逻辑可以作为属性直接添加到你的实体逻辑里。 最常见的用例与密码散列和获取全名有关,这时可以使用 getter 方法,但是要注意不要过度使用,避免给实体承担大量的业务逻辑。
import { Exclude } from 'class-transformer';
export class UserEntity {
id: number;
firstName: string;
lastName: string;
get fullName() {
return this.firstName + " " + this.lastName;
}
}
8. 使用集中命名导出
你可以从同一个文件夹中导入所有类,而不是从不同的文件中导入你的类。如有以下目录:
// index.ts
export * from './createPost.dto';
export * from './editPost.dto';
export * from './editPostCategory.dto';
export * from './editPostStatus.dto';
// 推荐
import { CreatePostDto, EditPostDto } from './dto';
// 不推荐
import { CreatePostDto } from './dto/createPost.dto';
import { EditPostDto } from './dto/editPost.dto';
今天的文章Nest.js 实践总结分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18227.html