NestJS事始め
はじめに
expressの書き方に疲れてspringを使おうか迷っていた今日このごろ。
A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.
と謳っているNestJSなるフレームワークがあると聞いたので触ってみる。
TL;DR.
Install
公式のcliがあるのでサクッとインストール。
$ npm install -g @nestjs/cli
Projectの作成
$ nest new project-name > npm か yarnどっち使うか聞かれるので好みの方を選択
これでアプリの雛形が作成される。 生成されるファイルは下記の通り。
. ├── README.md ├──node_modules │ └── 省略 ├── nest-cli.json ├── nodemon-debug.json ├── nodemon.json ├── package-lock.json ├── package.json ├── src │ ├── app.controller.spec.ts │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ └── main.ts ├── test │ ├── app.e2e-spec.ts │ └── jest-e2e.json ├── tsconfig.build.json ├── tsconfig.json └── tslint.json
とりあえず起動してみる
@nestjs/cli
は後述するが色々ファイルを生成してくれる。
してくれるが、起動してくれる機能は無いので生成されたpackage.json
に書いてあるnpm script
を使う。
port3000で起動するので、とりあえずcurlで叩いてみる。
$ npm start [Nest] 45934 - 06/05/2019, 10:08 PM [NestFactory] Starting Nest application... [Nest] 45934 - 06/05/2019, 10:08 PM [InstanceLoader] AppModule dependencies initialized +19ms [Nest] 45934 - 06/05/2019, 10:08 PM [RoutesResolver] AppController {/}: +7ms [Nest] 45934 - 06/05/2019, 10:08 PM [RouterExplorer] Mapped {/, GET} route +6ms [Nest] 45934 - 06/05/2019, 10:08 PM [NestApplication] Nest application successfully started +3ms $ curl localhost:3000/ > Hello World!
無事動いているようなので手を加えていってみる。
Controller,Serviceを追加してみる
公式サイトのDocumentを参考にしながら、新しいController,Serviceを作ってみる。
# ファイルの生成とmoduleへの追加を自動でしてくれる $ nest generate controller sample > CREATE /src/sample/sample.controller.spec.ts (493 bytes) > CREATE /src/sample/sample.controller.ts (101 bytes) > UPDATE /src/app.module.ts (397 bytes) # `g`はgenerateのエイリアス。 sは`service`のエイリアス。(controllerのエイリアスは`co`) $ nest g s sample > CREATE /src/sample/sample.service.spec.ts (460 bytes) > CREATE /src/sample/sample.service.ts (90 bytes) > UPDATE /src/app.module.ts (597 bytes)
生成されたファイル
controller
import { Controller } from '@nestjs/common'; @Controller('sample') export class SampleController {}
service
import { Injectable } from '@nestjs/common'; @Injectable() export class SampleService {}
Controller,Serviceをちょっと修正
このままでは増えただけなので、ちゃんと中身を書いていく。 とりあえずGET,POST,PUT,DELETE辺りを実装してみる。
Controller
公式サイトのControllerを参考にしながら、書いていく。
色々アノテーションを付けた。今回使って無いのもあるので、詳しくはこちらから。
import {Body, Controller, Delete, Get, HttpCode, Param, Post, Put, Req} from '@nestjs/common'; import {SampleService} from './sample.service'; @Controller('sample') export class SampleController { constructor(private readonly sampleService: SampleService) {} @Get() public getSample(): string { return this.sampleService.getSample(); } /** * パスの値を可変にしたい場合、express同様`:変数名`でOK * @param params Expressのreq.paramsと同義 */ @Get(':id') public getSamplePath(@Param() params): string { return this.sampleService.getSampleById(params.id); } /** * requestの全量は`@Req()`をつけることで取得できる * @param req Expressのreqと同義 */ @Post() @HttpCode(201) public postSample(@Req() req): any { return this.sampleService.registerSample(req.body); } /** * Putサンプル * @param params パスから受け取る * @param body Expressのreq.bodyと同義。bodyだけ取得できる */ @Put(':id') public putSample(@Param() params, @Body() body): any { return this.sampleService.updateSample(params.id, body); } /** * HttpCodeでレスポンスのステータスコードを指定できる。 * @param id 直接取得したい場合は`@Param()`の引数に変数名を指定してあげればOK */ @Delete(':id') @HttpCode(204) public deleteSample(@Param('id') id: string): void { this.sampleService.deleteSample(id); } }
Service
こちらはデフォルトとにならってメソッドを増やしただけ。
import { Injectable } from '@nestjs/common'; @Injectable() export class SampleService { public getSample(): string { return 'sample service!'; } public getSampleById(id: string): string { return `id is ${id}`; } public registerSample(param: any): any { return {message: 'OK', result: param}; } public updateSample(id: string, param: any): any { return {message: id, result: param}; } public deleteSample(id: string): void { console.log(`${id} is deleted`); } }
叩いてみる
$ curl localhost:3000/sample > sample service! $ curl localhost:3000/sample/sampleId > id is sampleId $ curl -XPOST -H "Content-Type:application/json" localhost:3000/sample -d '{"id": "sampleId", "title": "sample", "message": "sample message"}' | jq . >{ > "message": "OK", > "result": { > "id": "sampleId", > "title": "sample", > "message": "sample message" > } >} $ curl -XPUT -H "Content-Type:application/json" localhost:3000/sample/sampleId -d '{"title": "sample", "message": "sample message"}' -v | jq . >{ > "message": "sampleId", > "result": { > "title": "sample", > "message": "sample message" > } >} $ curl -XDELETE localhost:3000/sample/sampleId -v > ... >< HTTP/1.1 204 No Content >< X-Powered-By: Express >< Date: Wed, 05 Jun 2019 14:49:40 GMT >< Connection: keep-alive
HTMLを返せるようにする
HTML
まず返すHTMLファイルを作る。
ファイルは下記のような箇所に配置しておく。
. ├── README.md ├── nest-cli.json ├── nodemon-debug.json ├── nodemon.json ├── package-lock.json ├── package.json ├── src ├── test ├── tsconfig.build.json ├── tsconfig.json ├── tslint.json └── views # ここを追加 └── index.html # 追加したHTML
main.ts修正
自動生成されたmain.ts
に追記する。
これも同じく公式サイトを参考に書いていく。
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import {NestExpressApplication} from '@nestjs/platform-express'; import {join} from 'path'; async function bootstrap() { // createの後ろに型を追加 const app = await NestFactory.create<NestExpressApplication>(AppModule); // ファイルが入っているフォルダを指定 app.useStaticAssets(join(__dirname, '..', 'views')); await app.listen(3000); } bootstrap();
動かしてみる
npm start
で起動した後、localhost:3000
にアクセス。
下記の画像の用にHTMLが返ってくればOK。
Helmetを導入する
expressでとりあえず入れとけって風潮があるhelmet
を導入してみる。
これも公式サイトにあるので参考にしてやる。
helmetインストール
$ npm install --save helmet
main.ts改修
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import {NestExpressApplication} from '@nestjs/platform-express'; import {join} from 'path'; // import追加 import * as helmet from 'helmet'; async function bootstrap() { const app = await NestFactory.create<NestExpressApplication>(AppModule); app.useStaticAssets(join(__dirname, '..', 'views')); // ここでhelmetを使うよう修正 app.use(helmet()); await app.listen(3000); } bootstrap();
まとめ
今回はnest.jsを使ってみた。
謳っているだけあって、全般的にAngularに似てる感じ。
Controllerの書き方とかはSpringに似てるのかなと思った。
expressよりも書きやすいしデフォルトでtsだし、個人的にはとても良さげ。
多分SSRとかもできるはずなのでいずれ調べたいところ。
これからガンガン使ってみようと思う。