Table of contents
- Code repository: https://github.com/nestjs/nest
- Official documentation: https://docs.nestjs.com/
- Chinese documentation: https://docs.nestjs.cn/
Install
# 如果是 node.js 10 之后的版本,需要加 --ignore-engines 来忽略一些不兼容库的警告
npm i -g @nestjs/cli --ignore-engines
# 或
yarn global add @nestjs/cli --ignore-engines
getting started document
- Attribute transformation: class-transformer
- Attribute validation: class-validator
Tips
Asynchronous method optimization
Reduce unnecessary async/await wrappers. The sample code is as follows:
function test() {
const deferred = {
promise: undefined,
resolve: undefined
};
deferred.promise = new Promise((resolve) => {
deferred.resolve = resolve;
});
setTimeout(() => {
deferred.resolve('hello world');
}, 1000);
return deferred.promise;
}
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {
}
// 以下两种写法都能运行,推荐使用第一种
@Get('/test')
getTest(): Promise<string> {
return test();
}
@Get('/test2')
async getTest2(): Promise<string> {
return await test();
}
}
In the same way, except in the Controller, the inner methods in Model, Service and other places can be optimized, because the outer layer has already brought it when calling await
. At the same time, you also need to pay attention to the return type of each method and develop good habits.
Using the Fastify framework
There is no documentation for that part, just a sample project: https://github.com/nestjs/nest/tree/master/sample/10-fastify
yarn remove @nestjs/platform-express
yarn remove @types/express
yarn add @nestjs/platform-fastify
Modify main.ts
the file:
import {
NestFactory } from '@nestjs/core';
// 新增引用
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import {
AppModule } from './app.module';
async function bootstrap() {
// 原有代码:
// const app = await NestFactory.create(AppModule);
// 替换代码:
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
await app.listen(3000);
console.log(`Application is running on: ${
await app.getUrl()}`);
}
bootstrap();
Open-API(Swagger)
Currently there are only English documents, no Chinese documents. Address: https://docs.nestjs.com/openapi/introduction
Use with Fastify:
yarn add @nestjs/swagger
yarn add fastify-swagger
# [Nest] 7253 - 2020/07/08 下午4:42:59 [PackageLoader] The "fastify-swagger" package is missing. Please, make sure to install this library ($ npm install fastify-swagger) to take advantage of SwaggerModule. +37ms
# 如果出现类似报错,使用2.x版本重试
yarn add fastify-swagger@^2.6.0
Sample code:
import {
NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import {
DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import {
AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
const options = new DocumentBuilder()
.setTitle('Cats example')
.setDescription('The cats API description')
.setVersion('1.0')
.addTag('cats')
.addBearerAuth()
.build();
// 生成的 JSON 格式文档,可以导出静态化
const document = SwaggerModule.createDocument(app, options);
// 注入, 访问 http://localhost:3000/api 可以访问
SwaggerModule.setup('api', app, document);
await app.listen(3000);
console.log(`Application is running on: ${
await app.getUrl()}`);
}
bootstrap();
Module code can refer to the sample project of Express Swagger: https://github.com/nestjs/nest/tree/master/sample/11-swagger
Generate Open-API.json file sample code:
import {
resolve } from 'path';
import {
writeFileSync } from 'fs';
import {
NestFactory } from '@nestjs/core';
import {
FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import {
DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import {
AppModule } from './app.module';
async function bootstrap() {
const app = (await NestFactory.create) < NestFastifyApplication > (AppModule, new FastifyAdapter());
const options = new DocumentBuilder()
.setTitle('Cats example')
.setDescription('The cats API description')
.setVersion('1.0')
.addTag('cats')
.addBearerAuth()
.build();
// 生成的 JSON 格式文档,可以导出静态化
const document = SwaggerModule.createDocument(app, options);
writeFileSync(resolve(__dirname, '../api.json'), JSON.stringify(document, null, 2), {
encoding: 'utf8' });
}
bootstrap();
E2E Testing
Still haven't found the document, please refer to an example test source code: https://github.com/nestjs/nest/blob/master/integration/hello-world/e2e/fastify-adapter.spec.ts
import {
Test, TestingModule } from '@nestjs/testing';
import {
AppModule } from './../src/app.module';
// 新增引用
import {
FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import {
expect } from 'chai';
describe('AppController (e2e)', () => {
let app: NestFastifyApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule]
}).compile();
// 修改 app 创建
app = moduleFixture.createNestApplication < NestFastifyApplication > new FastifyAdapter();
await app.init();
});
it('/ (GET)', () => {
// return request(app.getHttpServer())
// .get('/')
// .expect(200)
// .expect('Hello World!');
// 改用 inject 方式,不用 supertest
return app
.inject({
method: 'GET',
url: '/'
})
.then(({
payload }) => expect(payload).to.be.eql('Hello World!'));
});
});
Logger
npm i --save nestjs-pino
npm i --save-dev pino-pretty
The main.ts entry file imports:
import {
Logger } from 'nestjs-pino';
const app = await NestFactory.create(MyModule, {
logger: false });
app.useLogger(app.get(Logger));
The app.module.ts file introduces:
import {
LoggerModule } from 'nestjs-pino';
@Module({
imports: [LoggerModule.forRoot()],
controllers: [AppController],
providers: [MyService]
})
class MyModule {
}
Example of usage in Controller:
import {
Logger } from 'nestjs-pino';
@Controller()
export class AppController {
constructor(private readonly myService: MyService, private readonly logger: Logger) {
}
@Get()
getHello(): string {
// pass message
this.logger.log('getHello()');
// also we can pass context
this.logger.log('getHello()', AppController.name);
return `Hello ${
this.myService.getWorld()}`;
}
}
Or use PinoLogger
(recommended):
// my.service.ts
import {
PinoLogger, InjectPinoLogger } from 'nestjs-pino';
@Injectable()
export class MyService {
// regular injecting
constructor(private readonly logger: PinoLogger) {
}
// regular injecting and set context
constructor(private readonly logger: PinoLogger) {
logger.setContext(MyService.name);
}
// inject and set context via `InjectPinoLogger`
constructor(@InjectPinoLogger(MyService.name) private readonly logger: PinoLogger) {
}
getWorld(...params: any[]) {
this.logger.info('getWorld(%o)', params);
return 'World!';
}
}
Startup script modification:
nest start --watch | pino-pretty
Graphql
- Chinese documentation: https://docs.nestjs.cn/7/graphql
- English documentation: https://docs.nestjs.com/graphql/quick-start
- Graphql Code First project example: https://github.com/nestjs/nest/tree/master/sample/23-graphql-code-first
- Sample Graphql Schema First project: https://github.com/nestjs/nest/tree/master/sample/12-graphql-schema-first
depends on apollo-server
.