create-nuxt-app で生成されたNuxt.jsプロジェクトのserver/index.js の実行内容を調査してみた

# 概要

Nuxt.jsはcreate-nuxt-appを使うことで簡単にSSRのプロジェクトを作ることができますが、イマイチ中がどのように動いているか知らなかったので、

```bash
#開発モード
$ npm run dev

#productionモード
$ npm run build
$ npm run start
```

開発モードやproductionモードで実行した時に自動生成されたindex.js内で何が起きているのかを少し調べてみました。

## 環境

- Nuxt.js 2.8.1
    - express, ssrモードでプロジェクトを作成
- Node.js 10.15.3
- npm 6.9.0

# require　
```js
const express = require('express')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const app = express()

const config = require('../nuxt.config.js')
config.dev = !(process.env.NODE_ENV === 'production')
```

ログモジュールである[consola](https://github.com/nuxt/consola)をrequireしている。
また、nuxtモジュールから [Nuxt](https://ja.nuxtjs.org/api/internals-nuxt/)クラスと[Builder](https://ja.nuxtjs.org/api/internals-builder/)クラスをrequireしている。
また、express インスタンスを作成している。

## Nuxt クラス
Nuxt.jsを利用する上でのコアクラス。公式では、「すべてのモジュールとクラスが通信できるようにするためのコアのコンテナ」と説明されている。[ソースコード](https://github.com/nuxt/nuxt.js/blob/v2.8.1/packages/core/src/nuxt.js)を見ると、Nuxt.jsを動作させるためのサーバやモジュールの準備をしているようです。

## Builder クラス
ソースコードをビルドするためのクラス。
productionでは、ビルドコマンドが別途用意されているため、開発モードでのみ使用されるようです。

## config
Nuxt.jsのconfigファイルを読み込み、またNODE_ENVを確認して開発モードかどうか決定している。

# start メソッド内

```js
async function start() {
  // Init Nuxt.js
  const nuxt = new Nuxt(config)

  const { host, port } = nuxt.options.server

  // Build only in dev mode
  if (config.dev) {
    const builder = new Builder(nuxt)
    await builder.build()
  } else {
    await nuxt.ready()
  }

  // Give nuxt middleware to express
  app.use(nuxt.render)

  // Listen the server
  app.listen(port, host)
  consola.ready({
    message: `Server listening on http://${host}:${port}`,
    badge: true
  })
}
start()
```

非同期のstartメソッドを用意し、それを実行している。

## Nuxt.jsの初期化

```js
const nuxt = new Nuxt(config)
```

設定ファイルを引数にして、Nuxtクラスのインスタンスを生成する。
この時、内部では以下の処理が実行されている。


- [nuxt.js#20](https://github.com/nuxt/nuxt.js/blob/v2.8.1/packages/core/src/nuxt.js#L20)
    - 引数に設定されたconfigの解決を行います。この処理で、ユーザが指定していないconfigはすべてdefault値が設定されるようです。
- [nuxt.js#L23-L24](https://github.com/nuxt/nuxt.js/blob/v2.8.1/packages/core/src/nuxt.js#L23-L24)
    - コアコンポーネントであるResolverクラスとModuleContainerクラスをインスタンス化します。
    - ResolverクラスはAliasなどのパス解決を行ってくれます。設定ファイルでいうと、下記の辺りです。
        - https://ja.nuxtjs.org/guide/configuration/#modulesdir
        - https://ja.nuxtjs.org/guide/configuration/#srcdir
        - https://ja.nuxtjs.org/guide/configuration/#rootdir
        - また、ESMの解決も行ってくれます。
    - [ModuleContainer](https://ja.nuxtjs.org/api/internals-module-container)クラスはすべてのモジュールを持つコンテナです。呼び出しはすべてこのコンテキスト上で行います。
- [nuxt.js#37-L47](https://github.com/nuxt/nuxt.js/blob/v2.8.1/packages/core/src/nuxt.js#L37-L47)
    - Nuxt.js内にあるserver機能の初期化を行い、ready状態にします。

# 開発モードとproductionモード

```js
// Build only in dev mode
if (config.dev) {
  const builder = new Builder(nuxt)
  await builder.build()
} else {
  await nuxt.ready()
}
```

開発モードの場合、Builderクラスをインスタンス化し、buildメソッドを実行します。
productionモードの場合、すでにbuild済みのはずなので、[readyメソッド](https://github.com/nuxt/nuxt.js/blob/v2.8.1/packages/server/src/server.js#L47-L69)を実行します。

# Nuxt.jsをexpressのミドルウェアとして与える

```js
// Give nuxt middleware to express
app.use(nuxt.render)
```

nuxt.renderでミドルウェアに与えられているのは、[server.js#L34](https://github.com/nuxt/nuxt.js/blob/v2.8.1/packages/server/src/server.js#L34)で生成された[connect](https://www.npmjs.com/package/connect)のappです。[ミドルウェアを追加](https://github.com/nuxt/nuxt.js/blob/v2.8.1/packages/server/src/server.js#L206-L207)したりもしています。

# サーバ起動

```js
app.listen(port, host)
consola.ready({
  message: `Server listening on http://${host}:${port}`,
  badge: true
})
```

最後に、ポートとホストを設定してサーバを起動します。