見出し画像

Node.jsを7年使ったエンジニアがNode.js フレームワークを実際にコードで紹介!Express, Koa, Fastify and NestJS

改めましてこんにちは。エアークローゼットアドベントカレンダー2021 2日目は昨日に引き続きCTOの辻(Twitter)がお送りしていきます。
今回はNode.js使って7年目の私が、実際にエアークローゼットで使っているNode.jsでメジャーな4つのフレームワークについて紹介しつつ、具体的なコード例を出していけたらと思います!(主なコード例については後日追加予定です。)

今日書かないフレームワーク

エアークローゼットでは基本的に軽量なフレームワークを採用しているため、フルスタック系のフレームワークはありません。具体的には、LoopbackMeteorSailsなどです。また、Hapiも使っていないので書いておりません。それらのフレームワークについては本記事は取り扱いませんのでご了承下さい。

Express(スター数:55.1k)

・最も老舗なフレームワークのひとつ
・Node.jsフレームワークの基礎
・最軽量のフレームワーク
・ミドルウェアが豊富
・ドキュメントが豊富

エントリーナンバー1番は言わずとしれたNode.jsフレームワークの老舗。Node.js使ったことがない人でも一度では聞いたことがあるのでは。
今日紹介するものすべてに共通するのですが、Node.jsのフレームワークは非常に軽量なものばかりです。(今日は紹介しないloopbackが唯一それなりに使われてるフルスタック系のフレームワークです。)
中でもExpressはバージョンアップするたびに軽量化していったフレームワークで、単体ではほぼ何もしてくれません笑 そういった特徴があるからこそ今でも廃れずに使われているのかなと思います。実際のコードについては後述します。

Koa(スター数: 32k)

・Expressによく似ている
・非同期処理に強い
・Expressに比べるとミドルウェアもドキュメントも少ない

ここから一気に知名度が落ちるのではないでしょうか。KoaはExpressの開発チームが主にはコールバック地獄を解消することを目的に新規で作り直したフレームワークで、そのためExpressに非常によく似ています。
使う感覚としてはExpressのミドルウェアでgenaratorやasync/awaitが使えるようになっただけの違いしかないので、Expressを使ったことがある人にとっては何の問題もなく使えるのではないでしょうか。expressに比べるとミドルウェアは少ないですが、欲しいミドルウェアは大体揃ってますし、自作するのも簡単なので困ることはあまりありません。実際のコードについて後述します。

Fastify(スター数: 21.3k)

ExpressHapiにインスパイアされたフレームワーク
・名前のとおりとにかく速い
・Express, Koaに比べるとフレームワークとして提供している機能が多い
・ドキュメントは少ない

Fastifyは兎にも角にも最速を目指したフレームワークで、私もいろんなサイトでNode.jsフレームワークのベンチマーク結果を見ますが、Fastifyが入っていればFastifyが最速な結果しか見たことがないくらいです。その代わり起動スピードはそんなに早くないです。
また、Expressにインスパイアされただけあって、記述方法もExpressに近いものを感じます。
ただExpressはほぼすべての機能をミドルウェアを上手く使って実装するのに対して、Fastifyでは用途に分けてミドルウェアの設定が可能になっているので、その点は多少リッチになっています。実際のコードについて後述します。

NestJS(スター数: 42.5k)

・TypeScript製
・コアにExpressとFastifyのどちらを使うか選べる
・デコレータ使える
・cliでテンプレート作成可能

一番の特徴はTypeScriptで開発されていることで、よほど待望されていたのか後発にも関わらずExpressに迫る勢いでスター数が伸びてます。
また、上にも書いたようにコアとしてExpressとFastifyのどちらを使うか選ぶことができて、それぞれのミドルウェアを使うこともできるので、良いとこ取りで使えるのもメリットのひとつ。
コードの感じはだいぶ変わるので最初は慣れないかもしれませんが、慣れると楽になります。実際のコードは後述します。

コード紹介

結局コード見るのが一番理解が早いと思うので、ここからは実際にそれぞれのフレームワークで実際にどう書くのかを紹介していけたらと思います。(徐々に追記していきます)

Hello World

express

$ npm install express @types/express
$ touch index.ts
$ ts-node-dev index.ts
// index.ts
import * as express from 'express';

const app = express();
const port = 3050;

app.get('/', (req, res) => {
 res.send('Hello World!');
});

app.listen(port, () => {
 console.log(`Example app listening at http://localhost:${port}`);
});

koa

$ npm install koa @types/koa
$ touch index.ts
$ ts-node-dev index.ts
// index.ts
import * as Koa from 'koa';

const app = new Koa();
const port = 3051;


app.use(ctx => {
 ctx.body = 'Hello World!';
});

app.listen(port, () => {
   console.log(`Example app listening at http://localhost:${port}`);
});

fastify

$ npm install fastify @types/node
$ touch index.ts
$ ts-node-dev index.ts
import { fastify } from 'fastify';

const app = fastify();
 
app.get('/', async (request, reply) => {
 reply.code(200);
 return 'Hello World!';
});
 
app.listen(3052, (err, address) => {
 console.log(`Example app listening at ${address}`);
});

NestJS
NestJSの場合、コマンドラインでHello Worldまで作られるので、最初から4ファイルあります。

$ npm install -g @nestjs/cli
$ nest new nestjs-sample
$ cd nestjs-sample
$ npm start
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
 const app = await NestFactory.create(AppModule);
 await app.listen(3000);
}
bootstrap();
// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
 imports: [],
 controllers: [AppController],
 providers: [AppService],
})
export class AppModule {}
//app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
 constructor(private readonly appService: AppService) {}

 @Get()
 getHello(): string {
   return this.appService.getHello();
 }
}
//app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
 getHello(): string {
   return 'Hello World!';
 }
}

logging

// 追加予定です

Router

追加予定です

Error Handling

追加予定です

OpenAPI(Swagger)

追加予定です

Validation

追加予定です

さいごに

今後どんどんコード追加予定です。