通过nest命令,可以很容易开始一个nest项目,可以查看文档:()[https://docs.nestjs.com/#installation],这里默认大家已经初始化好了项目, 我们讲一下项目目录划分的最佳实践:
empty-nestjs-project
├─.eslintrc.js
├─.gitignore
├─.prettierrc
├─README.md
├─nest-cli.json
├─package-lock.json
├─package.json
├─tsconfig.build.json
├─tsconfig.json
├─test
| ├─app.e2e-spec.ts
| └jest-e2e.json
├─src
| ├─app.controller.spec.ts
| ├─app.controller.ts
| ├─app.module.ts
| ├─app.service.ts
| └main.ts
刚生成的空项目中只有一个main入口文件和app,但真实项目肯定会创建多个类似的,所以需要一个友好的目录结构。 nest提供了多种不同职责的装饰器或者服务,有些需要和控制器放在一个目录,有些则需要放在公共的目录中,下面列出所有不同的职责文件类型,帮助大家理解:
- module
- controller
- service
- factory
- entity
- guard
- interceptor
- interface
- middleware
- pipes
- serializer
- job
我们的目录原则:
模型的目录
单个模型下的文件会放在同一个目录中,比如模型的控制器,model配置文件(entity),模型的服务函数,模型的数据生成器(factory) 类似如下:
├─src
| ├─app.controller.spec.ts
| ├─app.controller.ts
| ├─app.module.ts
| ├─app.service.ts
| ├─config.ts
| ├─main.ts
| ├─models
| | ├─user
| | | ├─user.controller.ts
| | | ├─user.entity.ts
| | | ├─user.factory.ts
| | | ├─user.module.ts
| | | ├─user.service.ts
| | | ├─interfaces
| | | | └user.interface.ts
| | | ├─dto
| | | | ├─create-user.dto.ts
| | | | ├─index.ts
| | | | └login-user.dto.ts
| | ├─store
| | | ├─store.controller.ts
| | | ├─store.entity.ts
| | | ├─store.factory.ts
| | | ├─store.module.ts
| | | ├─store.service.ts
| | | ├─dto
| | | | ├─index.ts
| | | | └insert-order-with-store.ts
这里module文件负责模型的注入,因为nest是通过iOC的方式来进行调用。
controller控制器负责配置restful api的接口,以及入口函数。
DTO负责接口接受的数据的结构定义,以及参数校验工作
数据库表的访问通过service,当store需要调用user时可以通过StoreModule的import来导入UserModule。(user.module需要export: [UserService])
公共的class和文件
├─src
| ├─common
| | ├─serializers
| | | ├─model.serializer.ts
| | | ├─responses
| | | | ├─error.serializer.ts
| | | | └success.serializer.ts
| | ├─pipes
| | | └validation.pipe.ts
| | ├─middleware
| | | ├─logger.middleware.ts
| | | └user.middleware.ts
| | ├─interfaces
| | ├─interceptors
| | | ├─response.interceptor.ts
| | | └sentry.interceptor.ts
| | ├─helpers
| | ├─guards
| | | └test.guard.ts
| | ├─exceptions
| | ├─entities
| | | └base.ts
| | ├─decorators
| | ├─constants
common有着最多的文件,主要负责一些公共的服务,并可以用在任何的模型中 比如
- response.interceptor.ts,负责包装返回的json结构
- validation.pipe.ts,负责实现class-validator的transform函数,校验请求的query参数
- logger.middleware.ts,负责对请求的时间做统计
其他的一些src下目录
- 数据库表的数据生成则是放在了database目录下
├─src
| ├─database
| | ├─seeders
| | | ├─address.seed.ts
| | | ├─category.seed.ts
| | | ├─sale-attr-key.seed.ts
| | | ├─slate-attr-value.seed.ts
| | | ├─spu.seed.ts
| | | ├─staff.seed.ts
| | | ├─store.seed.ts
| | | └user.seed.ts
| | ├─migrations
- 异步队列放在jobs下
├─src
| ├─jobs
- 配置放在config下
├─src
| ├─config
| | ├─database.config.ts
| | └redis.config.ts
- 权限的相关模型放在了authentication目录下
├─src
| ├─authentication
| | ├─auth.controller.ts
| | ├─auth.module.ts
| | ├─auth.service.ts
| | ├─authenticated.guard.ts
| | ├─local-auth.guard.ts
| | ├─local.strategy.ts
| | ├─session.serializer.ts
| | ├─wx-auth.service.ts
| | ├─interfaces
| | | └code2session.ts
| | ├─dto
| | | └wx-login.dto.ts
- 项目的相关文档
├─docs
| ├─Booking Server.xmind
| ├─Interface Order.xmind
| └接口开发顺序.xmind
FAQ:
- nestjs,是怎么识别各种文件的职责的?
a. nestjs自己的职责文件是通过装饰器的定义和类实现,比如middleware的声明:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}
这里通过实现NestMiddleware后,通过反射,nest可以执行对应的middleware
P.S. 很多职责类,其实nestjs是不区分的,比如service,它是不实现nest内置类的,所以需要在使用的地方,比如controller的constructor手动注入
b. typeorm的entity则是通过配置实现的:
database: {
type: 'postgres',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT, 10),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
entities: ['dist/**/*.entity.js'],
synchronize: true,
migrations: ['dist/database/migrations/*.js'],
logging: false,
cli: {
migrationsDir: 'migration',
},
seeds: ['dist/database/seeders/**/*.seed.js'],
factories: ['dist/**/*.factory.js'],
},