憧れのTypeScriptフルスタック環境がコマンド1発で作れる超軽量フレームワーク「frourio」

今年6月の[TypeScript Meetup #4](https://typescript-jp.connpass.com/event/177175/)で初公開されたTypeScript製フレームワーク「frourio (フルーリオ)」が今月のアップデートでめちゃくちゃカッコいい感じに仕上がっているので紹介します

frourioはフロントからバックエンド・ORマッパーまでのアプリ全体を一つのTypeScriptとして統合型チェックが可能になるフレームワークです
1つのディレクトリで完結するので一見するとモノリシックのようですが、型で繋がっていること以外はフロントとバックが個別のプロジェクト扱い（それぞれに別のpackage.jsonがある）なのでフロントはVercel、バックエンドはDockerでAWSにデプロイするみたいなことが可能です

![image](https://frouriojs.github.io/frourio/assets/images/architecture.png)

新しいfrourioの特徴

1. TypeScript製で最速のフレームワーク
1. コマンド1発でフロントSPA + RESTサーバー + ORマッパーの環境構築
1. Vercel製React Hooks「SWR」に対応
1. 関数にDependency Injectionが可能
1. ロゴがカワイイ

順番に解説していきます

## TypeScript製で最速のフレームワーク

誤解の無いように最初に伝えておくと、実用レベルでNode.jsフレームワークの世界最速は[Fastify](https://www.fastify.io/)です
FastifyにもTypeScriptの型定義はありますが、コード自体は普通のJavaScriptで書かれています

TypeScript製フレームワークというカテゴリでは名前のよく似た[Foxify](https://github.com/foxifyjs/foxify)が最速でした
（最後のリリースは2年以上前・・・）

そんなFastifyとFoxifyの間に割って入りNode.js全体で2位、TypeScript製では最速になったのが[frourio](https://github.com/frouriojs/frourio)です

| Framework          | Version          |  Requests/sec |  Latency |
| :----------------- | :--------------- | ------------: | -------: |
| fastify            | 3.7.0	          | 64,873	      | 1.45     |
| **frourio**        | **0.19.0**       | **64,457**    | **1.46** |
| foxify       | 0.10.20            | 57,810        | 1.64     |
| nest-fastify       | 7.4.4            | 57,303        | 1.65     |
| express            | 4.17.1	          | 11,972        | 8.24     |
| nest               | 7.4.4            | 10,025         | 9.86    |

出典：https://github.com/frouriojs/benchmarks

突然現れたfrourioが爆速なのにはカラクリがあって、サーバーのコアがFastifyなのです
すでにある速いエンジンをラップすれば速くなるのは当たり前・・・

しかしながら、Fastifyを自分で書くよりも高速に動作します
frourioはシンプルな関数を組み合わせる設計になっていることと、ルーティングでオーバーヘッドが発生しないようコンパイル時点で型情報を基に最適化することでFastify本来のパワーを引き出すフレームワークなのです

## コマンド1発でフロントSPA + RESTサーバー + ORマッパーの環境構築

※10/25現在、一部のWSL環境ではエラーが発生してインストールができません

Next.jsのcreate-next-app、Nuxt.jsのcreate-nuxt-app相当のコマンドがfrourioにもあるので環境構築は簡単です
Node.js v10系にはないflatMapを使っているのでv12/v14の環境で以下のコマンドを叩いてください

```sh
$ npx create-frourio-app
```

```sh
$ yarn create frourio-app
```

パッケージのダウンロードが終わったら、ターミナルに以下メッセージが表示され自動でブラウザが開きます
※ブラウザが開かない場合は手動でURLを打ち込んでください

```sh
open http://localhost:3000 in the browser
```
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/4d63ae62-bda4-7641-1ddb-e6ed9314e849.png)

「Directory name」は新規作成するプロジェクトのディレクトリ名を入力します
package.jsonのnameにも使われる名前です


frourioのコアはデフォルトで選択されているFastifyがおススメです
Expressに比べて日本語情報が少ないものの、開発は活発だし何よりベンチマークが5倍以上速いです
フロントエンドはNext.jsかNuxt.jsの好きな方を選んでください
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/c28b4d78-205d-3a5c-d911-56c94d99d3ec.png)
「Daemon process manager」までの項目についてもお好きなように
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/e50a4f10-471d-1517-3121-2d256bd62086.png)
ORマッパーはデコレータ不要で型がきっちり付くPrismaがおススメです
今回はちょっと動かしてみるだけなのでデータベースはSQLiteにするといいです
事前インストール不要でプロジェクト内に閉じた開発が出来ます
SQLiteで使う`.db`ファイルはデフォルトのまま
![無題3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/70d385ff-d176-fb0a-301c-cd65b2fde628.png)
依存性注入のサンプルコードを見たい場合はJestを選択しCreateボタンを押します
![無題4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/83166856-9e80-6e36-7a2a-367e9cc43db7.png)
画面にモーダルが現れ、ターミナルでインストールが始まります
![無題5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/af6e3393-6f3a-fea9-075c-a82723974247.png)
インストールが終わるとブラウザが自動でリロードされてNextかNuxtのTodoアプリが表示されます
インストールのあとにビルドの工程があるのでかなり時間がかかります
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/e60ddcf3-63fd-3e7a-3efa-11d5eb641ad8.png)

## Vercel製React Hooks「SWR」に対応

インストール時にNext.jsを選択すると、`pages/index.tsx`に以下のコードがあります
![無題6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/dc7163b4-fe1b-a33b-8b97-0fda016107e4.png)
10行目の`useAspidaSWR`というのがSWRのラッパーで、引数に渡した`apiClient.tasks`をキーとして`/tasks`にGETリクエストを行っています
返り値はSWRの返り値と全く同じです

実はこの引数がfrourioのコントローラと型で静的に繋がっているのです

`server/api/tasks/index.js`にこのAPIの型定義があります
`server/api`以降のディレクトリ名がそのままAPIのURLに対応してます
![無題7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/071c7771-6aec-4b0f-46fb-93da1f7fc1e9.png)
試しにresBodyの型をstringに変えてみると
![無題8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/7920b8aa-9a25-dea7-00b5-3c01d9072470.png)
Next.js: `pages/index.tsx`
![無題10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/e7d9d45c-2eee-80a9-e317-4ac9ae12682d.png)
frourio: `server/api/tasks/controller.ts`
![無題9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/111f3c59-5dbc-b6ac-9b61-d1428639e5e8.png)
Next.jsとfrourioの両方で型エラーが出るのがfrourioのスゴイところです

## 関数にDependency Injectionが可能

frourioはバリデータ以外全て関数で書きます
関数で書かれたコントローラーに依存性注入を行うパターンは一般に確立されていませんがfrourioでは「関数型DI」と呼んでいる方法を採用しています
インストール時にテストフレームワークとしてJestを選択するとfrourioのテストコードが含まれます

以下8行目でprismaオブジェクトを注入したfindAllTaskを定義
あとで依存性注入しやすいようにasでアップキャストしておきます
![無題11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/a0610d2c-912b-980c-c82c-363755516408.png)
以下7行目でfindAllTaskとprintをコントローラーに注入
![無題12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/0fdb76c4-90bf-2446-ca06-74197bd927e0.png)
好きなツールを使ってテストを記述
以下7行目のコントローラーはもちろん、8行目のfindAllTaskにも依存性注入が必要なので入れ子にしています
printは依存がないのでアロー関数を直接注入します
![無題13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/d62205ca-9dd9-d3ad-649f-41a83b83f63a.png)
実行結果
![無題14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/cb9c2419-1cd2-4125-4f5d-4f7f68917576.png)
よく見かけるクラスベースのDIに比べて非常に簡潔に記述出来ていることが伝わるでしょうか

これはvelonaという別のライブラリを取り込んで実現したものです
（正確にはfrourioでDIを行う方法を模索し続けた結果生まれたスピンオフライブラリです）

以下の記事が参考になります
[まだクラスへの依存性注入で消耗してるの？TS製の関数型DIヘルパー「velona」のススメ](https://qiita.com/m_mitsuhide/items/34474fcf5402e8606297)

## ロゴがカワイイ

海外のデザイナーに発注して作ってもらったカワイイキャラクターがロゴに使われています
![frourio-github-ogp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/59c5491f-0682-786e-1e6d-74b5baea2605.png)
気に入ったらGitHubにスターを押してやって下さい
[frourio](https://frourio.io)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Qiitaの解説記事から来てくれた人々のおかげでfrourioのGitHubスターがあっという間に100を超えました🎉🎉<br>可愛いロゴ（名前はまだない）とともにTypeScript界のRailsポジションを目指して開発を続けていきます！<a href="https://t.co/wxMmaRwmEA">https://t.co/wxMmaRwmEA</a></p>&mdash; Solufa (@m_mitsuhide) <a href="https://twitter.com/m_mitsuhide/status/1315132030745669632?ref_src=twsrc%5Etfw">October 11, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 参考記事

以下URLでfrourioの日本語解説記事が連載される予定です
[frourio でフロントエンドとバックエンドを一緒に静的型検査する](https://qiita.com/su8ru/items/08d4222af6ddb8eb218b)
[frourio でサクッと API 型定義 & コントローラーを書く](https://qiita.com/su8ru/items/e4ba6fd311ee3905d174)