Nuxt3 の Nitro の設定を少しだけ触ってみるよ

Qiita 初投稿です。

# 変更履歴

2022/08/29: モックサーバ化の設定間違ってたので修正しました。前のままだとうまく動きませんでした。


# Nitro って何？

Nuxt3 で採用されているサーバサイドのエンジンだよ。
Nuxt3 におけるサーバサイドAPIを生成したりするよ。
とっても早いし、ビルド結果も軽い。

## ググってもでてこないんだけど・・

`unjs nitro` でググれば一発


# 触って見るところ

Nuxt3 の `nuxt.config.ts` で nitro オプションを少し触ってみるよ

```ts:nuxt.config.ts
import { defineNuxtConfig } from "nuxt";

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
  srcDir: 'src',
  nitro: {
    // これ！
  }
});
```

## 型情報どうなってるの？

Nuxt3 公式のリファレンスによると・・
https://v3.nuxtjs.org/api/configuration/nuxt.config#nitro

![スクリーンショット 2022-08-26 12.43.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067027/0d748883-5769-ac4f-1c6e-fdb73fe5073c.png)

・・・・あ、Nitro の公式リファレンスに誘導されてる。


つまり、設定値はここを見れば良さそう。
https://nitro.unjs.io/config/



vscode だったら、 `nuxt.config.ts` の `nitro` のところを右クリックすれば型の実装に参照できて、
追ってみるとだいたいこんな感じの型情報にたどり着くよ。

```ts:(nitro:0.4.24) node_modules/nitropack/dist/index.d.ts
interface NitroConfig extends DeepPartial<NitroOptions> {
    extends?: string | string[] | NitroPreset;
}

interface NitroOptions {
    _config: NitroConfig;
    preset: string;
    logLevel: LogLevel;
    runtimeConfig: {
        app: {
            baseURL: string;
        };
        nitro: {
            /** @deprecated Use top-level routes option! */
            routes: NitroRoutesOptions;
        };
        [key: string]: any;
    };
    rootDir: string;
    srcDir: string;
    scanDirs: string[];
    buildDir: string;
    output: {
        dir: string;
        serverDir: string;
        publicDir: string;
    };
    storage: StorageMounts;
    // ... 中略
}
```

[ここ](https://nitro.unjs.io/config/ "nitro configuration")　に書いてある内容とほぼ同じ構成になっているっぽいのがわかる。

## 実際の値を確認するには・・？

Nuxt の [lifecycle hooks](https://v3.nuxtjs.org/guide/going-further/hooks "Nuxt3 Lifecycle Hooks") を使ったら表示できた。

```ts:nuxt.config.ts
import type { NitroConfig } from "nitropack";

export default defineNuxtConfig({
  hooks: {
    'nitro:build:before': (c: NitroConfig) => {
      console.dir(c, { depth: undefined })
    }
  }
```

ほぼ未設定だと、下のような値が表示された。

```js:nitro config
{
  rootDir: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app',
  srcDir: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src/server',
  dev: true,
  preset: 'nitro-dev',
  buildDir: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/.nuxt',
  scanDirs: [ '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src/server' ],
  renderer: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/core/runtime/nitro/renderer',
  errorHandler: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/core/runtime/nitro/error',
  nodeModulesDirs: [
    '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules',
    '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules',
    '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/node_modules'
  ],
  handlers: [],
  devHandlers: [],
  baseURL: '/',
  virtual: {},
  runtimeConfig: {
    public: {},
    app: { baseURL: '/', buildAssetsDir: '/_nuxt/', cdnURL: '' },
    nitro: { envPrefix: 'NUXT_' }
  },
  typescript: { generateTsConfig: false },
  publicAssets: [
    {
      dir: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/.nuxt/dist/client'
    }
  ],
  prerender: { crawlLinks: false, routes: [] },
  sourcemap: true,
  externals: { inline: [ 'nuxt/dist', 'nuxt3/dist' ] },
  alias: {
    'vue/compiler-sfc': 'vue/compiler-sfc',
    'vue/server-renderer': 'vue/server-renderer',
    vue: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/vue/dist/vue.cjs.js',
    'estree-walker': 'unenv/runtime/mock/proxy',
    '@babel/parser': 'unenv/runtime/mock/proxy',
    '@vue/compiler-core': 'unenv/runtime/mock/proxy',
    '@vue/compiler-dom': 'unenv/runtime/mock/proxy',
    '@vue/compiler-ssr': 'unenv/runtime/mock/proxy',
    '@vue/devtools-api': 'unenv/runtime/mock/proxy-cjs',
    '#paths': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/core/runtime/nitro/paths',
    '~~': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app',
    '@@': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app',
    '~': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src',
    '@': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src',
    assets: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src/assets',
    public: '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/src/public',
    '#app': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/app',
    'vue-demi': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/app/compat/vue-demi',
    '@vue/composition-api': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/app/compat/capi',
    '#head': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/node_modules/nuxt/dist/head/runtime',
    '#imports': '/Users/mewton/Workspace/sandbox/nuxt-sandbox/nuxt-app/.nuxt/imports'
  },
  replace: {
    'process.env.NUXT_NO_SSR': false,
    'process.dev': true,
    __VUE_PROD_DEVTOOLS__: false
  },
  rollupConfig: {
    plugins: [
      {
        name: 'nuxt:import-protection',
        enforce: 'pre',
        resolveId: [Function: resolveId]
      }
    ]
  }
}
```

Nuxt3 の設定がなんとなく nitro の設定に反映されてるっぽいのはわかる。

例えば、 Nuxt の設定側で alias を追加してみると、 nitro の設定側にも alias が反映されてる。 

```ts:nuxt.config.ts
export default defineNuxtConfig({
  alias: {
    '$': '/<rootDir>/test'
  }
```

# `server/api` のパスを変えてみる

`server/api` のパスを変えるには、 nitro の srcDir と scanDir をそれぞれ 変更後のパスにする必要がある。
しかし、 以下のように設定すると、 Nuxt 側の設定が上書きしてしまうので、うまくいかない。

```ts:nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    srcDir: resolve(__dirname, './hoge/server'),
    scanDirs: [resolve(__dirname, './hoge/server')]
  }
```

そこで、以下のように変えてみる

```ts:nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'nitro:config': (config: NitroConfig) => {
      const mockServerDir = resolve(__dirname, './hoge/server')
      config.srcDir = mockServerDir
      config.scanDirs = [mockServerDir]
    }
  }
```


この設定で、 API サーバのパスが `/hoge/server/api` に変わる。

srcDir は何となく、 nitro の API を構成するソースのディレクトリっぽいのはわかるが、
scanDirs は、公式のリファレンスによると、設定されているディレクトリをルートとして APIサーバを構築してくれるっぽい


## 応用例

例えば、 `server/api` を使ってテスト時はモックデータを返すようにすると、安直に作ると↓のようになる

```ts:server/api/sample.ts
import mock from 'sample.json'

export default defineEventHandler<Hoge>(async (event) => {
  if (isTestMode()) {
    return mock
  } else {
    const response = await $fetch('http://hogehoge.com/api')
    return response.data
  }
})
```

しかし、この方法では以下の理由でNGかと思う。

- 本番で TestMode かどうかの分岐があるのが不安. うっかり Test になってないか・・
- ビルドした際に、 .output 以下にテスト用のコードが含まれる

通常の Server API　と、 テスト用のモックデータを返す Server API を作って、
環境変数かなにかを使って切り替えれると良さそうだ

```ts:nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'nitro:config': (config: NitroConfig) => {
      if (isTestMode()) {
        const mockServerDir = resolve(__dirname, './test/server')
        config.srcDir = mockServerDir
        config.scanDirs = [mockServerDir]
      }
    }
  }
```

# まとめ

まだ　nitro の全オプションを触れていないけれど、オプションの触り方、確認の仕方が今回確認できた。

基本的には、 Nuxt3 側が用意する設定値をそのまま使えば大して困ることはないけれど、
例えばテスト時とか、全体の実装が複雑になってきたときに、
どうしても設定していく必要性はでてくるので、
試行錯誤の仕方だけでもそこそこ理解できたので良かったかな、と思う。