TL;DR: NestJS Frameworkを基に Node.js の backend スターターキットを構築しました。モノリシック なアーキテクチャを採用し、REST API を実装しています。
スターターキットはオープンソースでこちらのGithub Repoにて公開しています。
はじめに
Monstarlabでは最新の技術ソリューションを用いて、企業様が抱えるビジネス課題を解決するべく、製品開発およびコンサルティングを行っております。
Monstarlab のエンジニアは 4〜6 ヶ月毎に新しいお客様のプロジェクトに関わることが多いです。新しいプロジェクトを開始するたびに、技術スタックやソフトウェアアーキテクチャなど、選定に多くの時間を費やしていることに気付きました。
ダイレクトな解決策がない点は仕方ないのですが、上記については改善の余地があるという結論に達しました。例えばロガーサービス、リクエストバリデータ、JWT 認証ミドルウェアは毎回設計をし直す必要がありません。
Tada! そこで、こちらのスターターキットを用意しました。
ゲームプラン
このようなことが必要と思ったのは、私たちが初めてではありません。以前にもこの問題を解決しようとしましたが、意見の相違、モチベーション、時間管理など様々な理由で残念ながら失敗しています。 今回も同じような結果となることを心配していたので、異なる方法にて再度挑戦することにしました。
オープンソースにしておく
過去にこのような試みを行った際に、様々な理由からモチベーションが下がってしまったことが挙げられました。オープンソースにすることで、社外でも本プロジェクトが共有されるので、達成感がうまれました。
ハッカソン形式へ
このプロジェクトに貢献できるのはほとんどのメンバーが空いた時間にしかできませんでした。平日はクライアントプロジェクトに取り組むことが多いので、費やせる時間は非常に限られていました。 ブレインストームをした後に、私たちはこのスタータキットへの取り組みを週末に行うこととしました。Monstarlab はハッカソンを行ううえで多くのサポートをしてくれました。そのため、プロジェクトリリースやスケジュールを維持することができたのです。
We need to go left, no right
このスターターキットに何を入れるか。または何を入れてはいけないのか。このようなディスカッションはいつも難しく時間がかかるものでした。
このプロジェクトに貢献できるのはほとんどのメンバーが空いた時間にしかできませんでした。平日はクライアントプロジェクトに取り組むことが多いので、費やせる時間は非常に限られていました。
結果:
- スターターキットはモノリシックパターンとマイクロサービスに基づくものの2種類に別ける
- モノリシックの中で、さらに REST API と GraphQL を構築
- 軽量にする
- 高度な機能を含めるために、スターターキットに構築された実際の制作プロフェクトを紹介するサンプルソリユーションリポジトリを作成する
Features
前述のようにスターターキットはできるだけ軽量にすることが大原則です。そこを踏まえスタータキットに追加された機能をご紹介します。
認証
認証は、ほとんどの全てのプロジェクトで必要とされるものです。私たちは、ここで車輪の再発明したわけではありません。JWT 実装では、人気の高い Node.js ライブラリである PassportJS を使用して、重い作業のほとんどを代わりに行っています。bcrypt ライブラリを使用して、salts などを使ったパスワードのハッシュ化などが正しく行われていることを確認しています。よりエンタープライズグレードのプロジェクトでは、KeyCloak や Okta などの堅牢な ID 管理プロジェクトを使用するよう、皆さんにお勧めしたいと思います。今後、このような例を作っていくかもしれませんので、サンプルソリューションレポジトリにご注目ください。ご質問がございましたらお気軽にご相談ください。
Authorization
認証の上に、多くのプロジェクトで次に必要とされるのが可能です。認可とは、ユーザーが何をすることができるかを決定するプロセスを指します。私たちは、基本的なロールベースアクセスコントロール(RBAC)認可モジュールを実装しています。このモジュールがどのように動作し、どの程度簡単に使用できるかを確認するには、プロジェクトリポジトリ内のこのドキュメントファイルを参照してください。
ORM インテグレーション
ORM(Object-relational mapping とは、オブジェクト指向のパラダイムを使ってデータベースのデータを照会・操作できるようにする技術です。TypeORM はデータを操作するのに必要なコードをカプセル化するので、生の SQL を使う必要はもうありません。
DB マイグレーション
マイグレーションは、データベース内の既存のデータを保持しながら、アプリケーションのデータモデルと同期させるために、データベースのスキーマを段階的に更新する方法を提供します。DB スキーマのマイグレーションは、リレーショナル・データベースに関しては、常に多くの人にとって悪夢のようなものでした。TypeORM では、移行ファイルを簡単に生成することができます。
ロギング
NestJS には、独自のロガーが内蔵されています。しかし、それはテキストベースのロガーであり、プロダクションの要件には合いません。そこで、私たちは、非常に人気のあるプロダクションロギングパッケージである Winston をベースに、独自のカスタムロガーを実装しました。さらに良いのは、コールスタック全体でリクエストコンテキストを渡すことで、リクエスト ID、リクエストユーザーなどの追加情報を使ってコンテキストロギング を行うことができることです。
バリデーションリクエスト
ウェブアプリケーションに送信されるデータが正しいかどうかを検証することは、ベストプラクティスです。NestJS は、強力なclass-validator パッケージとその宣言的な検証デコレータを利用します。
ページ分割
REST API は、基本的なページングがないと完全とは言えません。私たちは、limit や offset といった単純なページネーションパラメータのサポートを追加しました。また、レスポンスには常に meta と呼ばれる子プロパティが含まれます。このプロパティには、リソースの総数などの情報が含まれており、フロントエンドアプリケーション側でのページネーションの実装をさらにスムーズにします。
Docker 準備
Need we say more?
自動生成された OpenAPI
これは NestJS で最も愛されている機能の一つです。OpenAPI 仕様は、RESTful な API を記述するために使用される、言語に依存しない定義フォーマットです。Nest では、デコレータを利用してこのような仕様を生成するための専用モジュールを提供しています。
追加機能
上記の機能以外にも、私たちのスターターキットには、prettier integration、commit-linting husky hooks、package import sorting、SonarCloud github actions、データベース依存のための docker-compose など、たくさんの細かい素晴らしい機能が搭載されています。
最後に
先日、Monolithic + REST API をベースとしたスターターキットのメジャーバージョンをリリースしました。 長い間「作業中」でしたが、ようやく皆さんに試していただき、貴重なフィードバックを提供できる準備が整いました。
What's next
ChangeLog の自動生成
このスターターキットのバックログは、これが最後です。この機能を最後に、このスターターキットに手をつけることはしばらくないと考えています。
次のロードマップは、GraphQL を使用したスターターキットです。
リソース
Article Photo by Gaelle Marcel
Docker Meme Photo by Meme Generator