Upgrade to Pro — share decks privately, control downloads, hide ads and more …

NestJS a progressive web framework

jiko21
February 12, 2020

NestJS a progressive web framework

関西Node学園#9での発表資料です
GitHub: https://github.com/jiko21/nest-todo-rest

jiko21

February 12, 2020
Tweet

More Decks by jiko21

Other Decks in Technology

Transcript

  1. Grad Student @ Kyoto univ Frontend / Serverside Engineer Android

    DeveloperͩͬͨΓ΋͢Δ Love: Vue.js, TypeScript, Kotlin, Golang… @jiko_21 (a.k.a Daiki Kojima) @jiko_21 @jiko21
  2. Controllers • ϧʔςΟϯάΛ୲͏ • pathͱmethod͕
 ରԠ @Controller('todos') export class TodosController

    { constructor(private readonly todosService: TodosService) {} @Get() getTodos(): Promise<ITodo[]> { return this.todosService.findAll(); } @Get(':id') getTodo(@Param('id', new ParseIntPipe()) id: number): Promise<ITodo> { return this.todosService.findById(id); } @Post('') createTodo(@Body() todoDao: TodoDao): Promise<ITodo> { return this.todosService.create(todoDao) } … }
  3. Controllers • ϧʔςΟϯάΛ୲͏ • pathͱmethod͕
 ରԠ @Controller('todos') export class TodosController

    { constructor(private readonly todosService: TodosService) {} @Get() getTodos(): Promise<ITodo[]> { return this.todosService.findAll(); } @Get(':id') getTodo(@Param('id', new ParseIntPipe()) id: number): Promise<ITodo> { return this.todosService.findById(id); } @Post('') createTodo(@Body() todoDao: TodoDao): Promise<ITodo> { return this.todosService.create(todoDao) } … } ! Ξϊςʔγϣϯ Ͱ
 NFUIPEͱQBSBNɺQBUIΛઃఆ
  4. • ϧʔςΟϯάΛ୲͏ • pathͱmethod͕
 ରԠ Controllers @Controller('todos') export class TodosController

    { constructor(private readonly todosService: TodosService) {} @Get() getTodos(): Promise<ITodo[]> { return this.todosService.findAll(); } @Get(':id') getTodo(@Param('id', new ParseIntPipe()) id: number): Promise<ITodo> { return this.todosService.findById(id); } @Post('') createTodo(@Body() todoDao: TodoDao): Promise<ITodo> { return this.todosService.create(todoDao) } … }
  5. • ϧʔςΟϯάΛ୲͏ • pathͱmethod͕
 ରԠ Controllers @Controller('todos') export class TodosController

    { constructor(private readonly todosService: TodosService) {} @Get() getTodos(): Promise<ITodo[]> { return this.todosService.findAll(); } @Get(':id') getTodo(@Param('id', new ParseIntPipe()) id: number): Promise<ITodo> { return this.todosService.findById(id); } @Post('') createTodo(@Body() todoDao: TodoDao): Promise<ITodo> { return this.todosService.create(todoDao) } … } DPOTUSVDUPSʹґଘ͢Δ0CKFDUΛ ॻ͍͓ͯ͘ͱ.PEVMF͕ґଘΛղܾ %*ɺޙड़ 

  6. Providers @Injectable() export class TodosService { constructor(@InjectRepository(Todo) todoRepo: Repository<Todo>) {}

    } @Controller('todos') export class TodosController { constructor(private readonly todosService: TodosService) {} } @Module({ imports: [TypeOrmModule.forFeature([Todo]),], providers: [TodosService], controllers: [TodosController], exports: [], }) export class TodosModule {}
  7. Providers @Injectable() export class TodosService { constructor(@InjectRepository(Todo) todoRepo: Repository<Todo>) {}

    } @Controller('todos') export class TodosController { constructor(private readonly todosService: TodosService) {} } @Module({ imports: [TypeOrmModule.forFeature([Todo]),], providers: [TodosService], controllers: [TodosController], exports: [], }) export class TodosModule {} *OKFDUBCMFΛ
 ࢦఆ
  8. Providers @Injectable() export class TodosService { constructor(@InjectRepository(Todo) todoRepo: Repository<Todo>) {}

    } @Controller('todos') export class TodosController { constructor(private readonly todosService: TodosService) {} } @Module({ imports: [TypeOrmModule.forFeature([Todo]),], providers: [TodosService], controllers: [TodosController], exports: [], }) export class TodosModule {} *OKFDUBCMFΛ
 ࢦఆ DPOUSPMMFSʹ
 ྲྀ͠ࠐΈ *OKFDU
  9. Imports @Module({ imports: [TypeOrmModule.forFeature([Todo]),], providers: [TodosService], controllers: [TodosController], exports: [],

    }) export class TodosModule {} @Module({ imports: [ TodosModule ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
  10. Imports @Module({ imports: [TypeOrmModule.forFeature([Todo]),], providers: [TodosService], controllers: [TodosController], exports: [],

    }) export class TodosModule {} @Module({ imports: [ TodosModule ], controllers: [AppController], providers: [AppService], }) export class AppModule {} JNQPSU͍ͯ͘͜͠ͱͰ
 .PEVMF͕࢖͑Δ
  11. ॻ͖ํͷҰྫ describe('TodosService', () => { let service: TodosService; let repository:

    Repository<Todo>; beforeEach(async () => { ... }); afterEach(async () => { ... }); it('findAll success', async () => { expect(await service.findAll()).toEqual(TODOS_ARAY); }); });
  12. ॻ͖ํͷҰྫ describe('TodosService', () => { let service: TodosService; let repository:

    Repository<Todo>; beforeEach(async () => { ... }); afterEach(async () => { ... }); it('findAll success', async () => { expect(await service.findAll()).toEqual(TODOS_ARAY); }); }); ֤ςετέʔε௚લʹ࣮ߦ
  13. ॻ͖ํͷҰྫ describe('TodosService', () => { let service: TodosService; let repository:

    Repository<Todo>; beforeEach(async () => { ... }); afterEach(async () => { ... }); it('findAll success', async () => { expect(await service.findAll()).toEqual(TODOS_ARAY); }); }); ֤ςετέʔε௚લʹ࣮ߦ ֤ςετέʔε௚ޙʹ࣮ߦ
  14. JestͰ͸Α͋͘Γ͕ͪͳ͜ͱ… • ୯ମςετͰɺ֎෦ϞδϡʔϧͷڍಈΛϞοΫ͍ͨ͠ • jest.spyOnͰϞοΫ it('getProducts', async () => {

    jest.spyOn(service, ‘findAll') .mockResolvedValue(PRODUCTS_ARRAY); expect(await controller.getProducts()) .toBe(PRODUCTS_ARRAY); }); @Get() getProducts(): Promise<IProducts[]> { return this.productsService.findAll(); } ςετର৅ ςετίʔυ
  15. JestͰ͸Α͋͘Γ͕ͪͳ͜ͱ… • ୯ମςετͰɺ֎෦ϞδϡʔϧͷڍಈΛϞοΫ͍ͨ͠ • jest.spyOnͰϞοΫ it('getProducts', async () => {

    jest.spyOn(service, ‘findAll') .mockResolvedValue(PRODUCTS_ARRAY); expect(await controller.getProducts()) .toBe(PRODUCTS_ARRAY); }); @Get() getProducts(): Promise<IProducts[]> { return this.productsService.findAll(); } ςετର৅ ςετίʔυ ͍ͭ͜ͷڍಈΛNPDL͍ͨ͠
  16. JestͰ͸Α͋͘Γ͕ͪͳ͜ͱ… • ୯ମςετͰɺ֎෦ϞδϡʔϧͷڍಈΛϞοΫ͍ͨ͠ • jest.spyOnͰϞοΫ it('getProducts', async () => {

    jest.spyOn(service, ‘findAll') .mockResolvedValue(PRODUCTS_ARRAY); expect(await controller.getProducts()) .toBe(PRODUCTS_ARRAY); }); @Get() getProducts(): Promise<IProducts[]> { return this.productsService.findAll(); } ςετର৅ ςετίʔυ ͍ͭ͜ͷڍಈΛNPDL͍ͨ͠ ͍ͭ͜ͷڍಈΛNPDL͢Δ
  17. NestJSͩͱ • moduleʹΑͬͯґଘղܾΛߦ͏ͷͰɺͦ͜ͰmockΛ
 ྲྀ͠ࠐΜͰ͠·͑͹OK describe('Todos Controller', () => { let

    controller: TodosController; let service: TodosService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [{ provide: TodosService, useValue: todoServiceMock, }], controllers: [TodosController], }).compile(); controller = module.get<TodosController>(TodosController); service = module.get<TodosService>(TodosService); }); }); export const todoServiceMock = { findAll: () => TODOS_ARAY, findById: (id: number) => TODOS_ARAY[0], create: (todoDao: TodoDao) => todoDao, }; mockؔ਺ ςετίʔυ
  18. πʔϧ܈͕๛෋ • ৭ʑͳ΋ͷ͕ఏڙ͞Ε͍ͯΔ • DI, test util, microservice support, WebSockets,

    RxJS • ʮNestJS͸ϓϥοτϑΥʔϜͰ͋Δʯɺͱ͍͏ࢥ૝͔Β
 ͜ͷΑ͏ʹͳ͍ͬͯΔ
  19. όοΫΤϯυ (http provider) Λબ୒Մೳ • package.jsonͱpackage-lock.jsonΛݟͯΈΔ { "name": "todo-app", "dependencies":

    { "express": { "version": "4.17.1", "resolved": “...”, "integrity": “...“, "requires": { ... }, "dependencies": { ... } }, } } { "name": "todo-app", "version": "0.0.1", "scripts": {}, "dependencies": { "@nestjs/common": "^6.7.2", "@nestjs/core": "^6.7.2", "@nestjs/platform-express": "^6.7.2", ... }, "devDependencies": { "@nestjs/cli": "^6.9.0", "@nestjs/schematics": "^6.7.0", "@nestjs/testing": "^6.7.1", "@types/express": "^4.17.1", ... }, }
  20. όοΫΤϯυ (http provider) Λબ୒Մೳ • package.jsonͱpackage-lock.jsonΛݟͯΈΔ { "name": "todo-app", "dependencies":

    { "express": { "version": "4.17.1", "resolved": “...”, "integrity": “...“, "requires": { ... }, "dependencies": { ... } }, } } { "name": "todo-app", "version": "0.0.1", "scripts": {}, "dependencies": { "@nestjs/common": "^6.7.2", "@nestjs/core": "^6.7.2", "@nestjs/platform-express": "^6.7.2", ... }, "devDependencies": { "@nestjs/cli": "^6.9.0", "@nestjs/schematics": "^6.7.0", "@nestjs/testing": "^6.7.1", "@types/express": "^4.17.1", ... }, }
  21. όοΫΤϯυ (http provider) Λબ୒Մೳ • ࣮͸NestJSͷhttp provider͸ࣗલͷ΋ͷͰ͸ͳ͍ • σϑΥϧτ͸Express •

    ଞͷhttp provider΋ར༻͢Δ͜ͱ͕Մೳ • Fastifyͱ͔
 → expressͷ2ഒ΄ͲϕϯνϚʔΫͰྑ͍ੑೳ • ͜ΕʹΑΓ༷ʑͳthird-party plugin͕ར༻Մೳʹ
  22. fastifyʹมߋ • ҎԼͷίϚϯυͰಋೖ
 • main.tsΛҎԼͷΑ͏ʹ͢Δ $ npm i @nestjs/platform-fastify import

    { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { FastifyAdapter } from '@nestjs/platform-fastify'; async function bootstrap() { const app = await NestFactory.create(AppModule, new FastifyAdapter()); await app.listen(3000); } bootstrap();
  23. Reference • Building a platform: NestJS from the ground up

    | Kamil Myśliwiec | jsPoland 2018
 https://youtu.be/f0qzBkAQ3mk • Document of NestJS: https://docs.nestjs.com/