Nuxt4でrootにtestディレクトリを作成したとき、app配下のモジュールが読み込めないときの対応

に公開

結論

  1. vitest.config.tsにaliasを追加
import path from 'path'
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'unit',
          include: ['test/unit/**/*.spec.ts'],
          environment: 'node',
        },
        // ここを追加する
        resolve: {
          alias: {
            '@': path.resolve(__dirname, './app/'),
          },
        },
        // ...
      },
    ],
  },
})
  1. test用のtsconfigを作成し、./test/tsconfig.test.jsonに保存。
{
  "compilerOptions": {
    "paths": {
      "@": [
        "../app"
      ],
      "@/*": [
        "../app/*"
      ],
    },
  },
  "include": [
    "../test/**/*",
  ],
  "exclude": []
}
  1. プロジェクトrootのtsconfig.jsonに追加
{
  // https://nuxt.com/docs/guide/concepts/typescript
  "files": [],
  "references": [
    // ...
    {
      "path": "./.nuxt/tsconfig.node.json"
    },
    // これを追加
    {
      "path": "./test/tsconfig.test.json"
    }
  ],
}

環境

nuxt 4.1.2
@nuxt/eslint 1.9.0
vitest 3.2.4

背景

Nuxt4の公式ドキュメントに従ってテストをセットアップしようとすると、モジュールが解決できない現象が発生する。

モジュール '@/utils/hoge' またはそれに対応する型宣言が見つかりません。ts(2307)
Cannot find module '@/utils/hoge' or its corresponding type declarations. ts(2307)

app配下、server配下にtestを作っても良いが、公式ドキュメントの書きようからしてrootにtestディレクトリを切っているように見える。

正しい方法であるかは怪しいが、暫定的な対応として備忘録に残す。

ゴール

階層を上がっていく形で、以下のようにimportすれば解決するが、Nuxt4には @# などの素晴らしいエイリアスがあるためtestでも同様に利用したい。

import { hoge } from "../../app/utils/hoge" // これはエラーにならない
import { hoge } from "@/utils/hoge" // app配下はこれで読み込むのが理想

Lintエラーにならず、かつ@エイリアスを用いてtestがpassすることをゴールとする。

手順

手順1: Vitest側の設定修正

vitest.config.ts に @を設定。これでlintエラーは発生するがテストは通るようになる。

import path from 'path'
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    projects: [
      {
        test: {
          name: 'unit',
          include: ['test/unit/**/*.spec.ts'],
          environment: 'node',
        },
        // ここを追加する
        resolve: {
          alias: {
            '@': path.resolve(__dirname, './app/'),
          },
        },
      },
    ],
  },
})

手順2: tsconfigの設定修正

tsconfigを見ると、app、server、sharedディレクトリそれぞれに対応する参照が用意されていることがわかる。

{
  // https://nuxt.com/docs/guide/concepts/typescript
  "files": [],
  "references": [
    {
      "path": "./.nuxt/tsconfig.app.json"
    },
    {
      "path": "./.nuxt/tsconfig.server.json"
    },
    {
      "path": "./.nuxt/tsconfig.shared.json"
    },
  ]
}

私は ./.nuxt/tsconfig.shared.json をコピーし、必要な部分を抽出して./test/tsconfig.test.json に保存した。(これはゴールに対する最小構成)

{
  "compilerOptions": {
    "paths": {
      "@": [
        "../app"
      ],
      "@/*": [
        "../app/*"
      ],
    },
  },
  "include": [
    "../test/**/*",
  ],
  "exclude": []
}

最後に

今回は @ だけに絞ったが~#も同様に設定可能。

この記事で同様のエラーが発生した人が一人でも救われると嬉しい。
Nuxtは大好きなフレームワークであるためもっと流行ることを願っている。そのためにTipsも積極的に書いていきたいと思う。

もし、もっとスマートな方法の提案や誤った手順を踏んでいるという指摘があれば、コメントいただけると非常に助かります。

Discussion