Nuxt.jsのServer Side RenderingモードでFastifyをserverMiddlewareとして使う話

おはこんにちばんは。
ハイパーエンジニアの[@FL1NE](https://twitter.com/FL1NE)です。


## 何
[Nuxt.js](https://ja.nuxtjs.org/)のServerSideRenderingモード(以下SSRモード)で開発する際に
[Nuxt.js](https://ja.nuxtjs.org/) + [Express](https://expressjs.com/ja/)という組み合わせはよく見かけますが、Expressよりも高速だと言われている[Fastify](https://www.fastify.io/)を組み合わせた例があまりなかったので組み合わせて使う方法をメモっておきます。

### リポジトリ
https://github.com/FL1NE/nuxt-fastify-example

### なんでserverMiddleware?
別で立てるのだったら別で立ててやればいいと思いますけど、Nuxt.jsのserverMiddlewareとして立てることによって以下の利点が生まれます。

- Nuxt.jsとセットで開発できるので管理が楽
- **Nuxt.jsとは別のポートをLISTENしなくていい。 (LISTENすることもできる)**
- ワンパッケージになるのでデプロイが楽
- ↑それらによってCORS関連の問題も基本起きない (はず)

ちなみにURLのパスでserverMiddlewareへのアクセスを判別する形をとります。
今回は `example.com/backend/`のように`/backend/*`へのアクセスをFastifyで受けるようにします。


## 下準備

### yarn create nuxt-appでnuxtアプリを作る

普通に作るだけ (必要なものだけ記載してます)

```
$ yarn create nuxt-app nuxt-fastify-example
  ? Programming language: TypeScript
  ? Rendering mode: Universal (SSR / SSG)
  ? Deployment target: Server (Node.js hosting)
```

とりあえず、`yarn dev`で動作確認して動くことは確認しておきましょう


## FastifyとNuxt.jsを繋ぐ

### Fastifyのインストール

普通にFastifyをインストールします。

```
$ yarn add fastify
```

### serverMiddlewareの作成

プロジェクトのルートディレクトリに `server/`ディレクトリを作成し、`index.ts`を作成します

```ts
import fastify from 'fastify'

export default function (req: Request, res: Response) {
  const app = fastify({
    ignoreTrailingSlash: true,
    logger: false,
  })

  // 普通にサーバーを立てる場合はこんな感じ
  // app.ready()が呼ばれる前にこの辺の処理を定義しないといけない
  app.get('/', (_request, reply) => {
    reply.send({
      server: true,
      endpoint: '/backend',
    })
  })

  app.ready().then(() => {
    app.server.emit('request', req, res)
  })
}

```

Fastify関連のコードは基本このファイルが中心となります。

[`fastify.server`がNodeコアの`server`オブジェクトを渡してくれる](https://www.fastify.io/docs/v1.14.x/Server/#server)ので、そこでつないであげる感じです。


### serverMiddlewareの登録

先ほど作成したserverMiddlewareを`nuxt.config.js`に登録します。

```ts
export default {
~~ 省略 ~~ 
  serverMiddleware: [{ path: '/backend', handler: '~/server/' }],
}
```

`path:` の指定を変更することでアクセスを受けるURLを任意の形に変更できます。
`handler:` には先ほどのserverMiddlewareを指定すればOKです。


## 動作確認

再び `yarn dev` を実行して動作を確認します。

```
$ yarn dev
```

`http://localhost:3000/`に接続するといつも通りのNuxt.jsのチュートリアルが表示されます。
![Screen Shot 2021-08-07 at 0.09.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127603/ddff3663-e38c-ee32-aa19-1fc42ad5d307.png)

次に先ほど作成したserverMiddlewareのfastifyに接続してみましょう。
`http://localhost:3000/backend/`
![Screen Shot 2021-08-07 at 11.42.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127603/ea834c2e-5dd2-35ee-b57c-7ff15f578d37.png)


無事にfastifyのレスポンスを取得できました。


## 終わりに

以上の手順でNuxt.jsとFastifyを組み合わせることができました。
これにより自前のバックエンドサーバーを一つのNode.jsサーバーで統括して管理・デプロイが行えるようになります。
今後タイミングを見てここにAPIサーバーを建てる記事なども追加できたらと思っています。

ではまたいつか！


### 宣伝等

**GUNCY'S (グンシーズ)**
[株式会社GUNCY'S](https://guncys.com/)では社内や顧客の要望などを一緒に解決へ導くメンバーを広く募集しています。
興味がある方は是非[採用ページ](https://guncys.com/lp/recruit/)をご覧ください！

**FRONTL1NE (フロントライン)**
[FRONTL1NE](https://frontl1ne.net/)は日本のデモシーンなどをはじめとしたクリエイティブな活動や、ゲーム、プログラミング、音楽、映像など様々な分野に興味を持つな人が集うWebサイト・コミュニティです。
是非[Webサイト](https://frontl1ne.net/)や[Discord](https://discord.gg/Z74m4qz)を覗いてみてください!

**Tokyo Demo Fest (東京デモフェスト)**
[Tokyo Demo Fest](http://tokyodemofest.jp/)は日本唯一のデモシーン(メガデモ)イベント = デモパーティです。
デモパーティは、コンピュータを用いたプログラミングとアートに 興味のある人々が日本中、世界中から一堂に会し、 デモ作品のコンペティション(コンポ)やセミナーなどを行います。 また、イベント開催中は集まった様々な人たちとの交流が深められます。
最新の情報は[Twitter](https://twitter.com/TokyoDemoFest)や[Webサイト](http://tokyodemofest.jp/)をご確認ください！