brand logo

ドキュメント

解決

Nuxt Kit はパスを解決するための一連のユーティリティを提供します。これらの関数は、現在のモジュールに対して、名前や拡張子が不明なパスを解決することを可能にします。

時には、現在のモジュールに対して、名前や拡張子が不明なパスを解決する必要があります。例えば、モジュールと同じディレクトリにあるプラグインを追加したい場合です。このようなケースを処理するために、nuxt はパスを解決するための一連のユーティリティを提供します。resolvePathresolveAlias は現在のモジュールに対してパスを解決するために使用されます。findPath は指定されたパスの中で最初に存在するファイルを見つけるために使用されます。createResolver はベースパスに対してリゾルバを作成するために使用されます。

resolvePath

Nuxt のエイリアスと拡張子オプションを考慮して、ファイルまたはディレクトリへのフルパスを解決します。パスが解決できない場合、正規化された入力パスが返されます。

使用法

import { defineNuxtModule, resolvePath } from '@nuxt/kit'

export default defineNuxtModule({
  async setup () {
    const entrypoint = await resolvePath('@unhead/vue')
    console.log(`Unhead entrypoint is ${entrypoint}`)
  },
})

function resolvePath (path: string, options?: ResolvePathOptions): Promise<string>

パラメータ

path: 解決するパス。

options: リゾルバに渡すオプション。このオブジェクトは以下のプロパティを持つことができます:

プロパティ必須説明
cwdstringfalseパスを解決するためのベース。デフォルトは Nuxt の rootDir。
aliasRecord<string,>{lang="ts"}falseエイリアスのオブジェクト。デフォルトは Nuxt の設定されたエイリアス。
extensionsstring[]false試すファイル拡張子。デフォルトは Nuxt の設定された拡張子。
virtualbooleanfalseNuxt VFS に存在するファイル(例えば、Nuxt テンプレートとして)を解決するかどうか。
fallbackToOriginalbooleanfalse解決されたパスが存在しない場合に、正規化された入力パスを返す代わりに元のパスにフォールバックするかどうか。

import { defineNuxtModule, resolvePath } from '@nuxt/kit'
import { join } from 'pathe'

const headlessComponents: ComponentGroup[] = [
  {
    relativePath: 'combobox/combobox.js',
    chunkName: 'headlessui/combobox',
    exports: [
      'Combobox',
      'ComboboxLabel',
      'ComboboxButton',
      'ComboboxInput',
      'ComboboxOptions',
      'ComboboxOption',
    ],
  },
]

export default defineNuxtModule({
  meta: {
    name: 'nuxt-headlessui',
    configKey: 'headlessui',
  },
  defaults: {
    prefix: 'Headless',
  },
  async setup (options) {
    const entrypoint = await resolvePath('@headlessui/vue')
    const root = join(entrypoint, '../components')

    for (const group of headlessComponents) {
      for (const e of group.exports) {
        addComponent(
          {
            name: e,
            export: e,
            filePath: join(root, group.relativePath),
            chunkName: group.chunkName,
            mode: 'all',
          },
        )
      }
    }
  },
})

resolveAlias

Nuxt のエイリアスオプションを考慮してパスエイリアスを解決します。

function resolveAlias (path: string, alias?: Record<string, string>): string

パラメータ

path: 解決するパス。

alias: エイリアスのオブジェクト。提供されない場合、nuxt.options.alias から読み取られます。

findPath

指定されたパスの中で最初に存在するファイルを解決しようとします。

使用法

import { defineNuxtModule, findPath } from '@nuxt/kit'
import { join } from 'pathe'

export default defineNuxtModule({
  async setup (_, nuxt) {
    // メイン (app.vue) を解決
    const mainComponent = await findPath([
      join(nuxt.options.srcDir, 'App'),
      join(nuxt.options.srcDir, 'app'),
    ])
  },
})

function findPath (paths: string | string[], options?: ResolvePathOptions, pathType: 'file' | 'dir'): Promise<string | null>

パラメータ

paths: 解決するパスまたはパスの配列。

options: リゾルバに渡すオプション。このオブジェクトは以下のプロパティを持つことができます:

プロパティ必須説明
cwdstringfalseパスを解決するためのベース。デフォルトは Nuxt の rootDir。
aliasRecord<string,>{lang="ts"}falseエイリアスのオブジェクト。デフォルトは Nuxt の設定されたエイリアス。
extensionsstring[]false試すファイル拡張子。デフォルトは Nuxt の設定された拡張子。
virtualbooleanfalseNuxt VFS に存在するファイル(例えば、Nuxt テンプレートとして)を解決するかどうか。
fallbackToOriginalbooleanfalse解決されたパスが存在しない場合に、正規化された入力パスを返す代わりに元のパスにフォールバックするかどうか。

createResolver

ベースパスに対してリゾルバを作成します。

createResolver に関する Vue School のビデオを視聴してください。

使用法

import { defineNuxtModule, createResolver } from '@nuxt/kit'

export default defineNuxtModule({
  async setup (_, nuxt) {
    const { resolve, resolvePath } = createResolver(import.meta.url)
  },
})

function createResolver (basePath: string | URL): Resolver

パラメータ

basePath: 解決の基準となるベースパス。文字列または URL で指定できます。

戻り値

createResolver 関数は以下のプロパティを持つオブジェクトを返します:

プロパティ説明
resolve(path: string) => string{lang="ts"}ベースパスに対してパスを解決する関数。
resolvePath(path: string, options?: ResolvePathOptions) => Promise<string>{lang="ts"}ベースパスに対してパスを解決し、Nuxt のエイリアスと拡張子オプションを考慮する関数。

import { createResolver, defineNuxtModule, isNuxt2 } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    nuxt.hook('modules:done', () => {
      if (isNuxt2()) {
        addPlugin(resolver.resolve('./runtime/plugin.vue2'))
      } else {
        addPlugin(resolver.resolve('./runtime/plugin.vue3'))
      }
    })
  },
})

tips

このセクションは公式ドキュメントの翻訳ではなく、本サイト独自の補足記事です。

Nuxtのパス解決ユーティリティとは?

Nuxtでモジュールやプラグインを開発する際、ファイルやディレクトリのパスを正確に解決することは非常に重要です。特に、名前や拡張子が不明な場合や、エイリアスを使っている場合は、手動でパスを組み立てるのが煩雑になりがちです。

Nuxtはこうした課題を解決するために、resolvePathresolveAliasfindPathcreateResolverといったパス解決用のユーティリティ関数を提供しています。これらを活用することで、Nuxtの設定やエイリアスを考慮した正確なパス解決が可能になり、開発効率が大幅に向上します。


まず結論:Nuxtのパス解決ユーティリティのポイント

  • resolvePath
    Nuxtのエイリアスや拡張子設定を考慮し、ファイルやディレクトリのフルパスを非同期で解決する。

  • resolveAlias
    エイリアス文字列を実際のパスに同期的に変換する。

  • findPath
    複数の候補パスの中から最初に存在するファイルやディレクトリを非同期で見つける。

  • createResolver
    ベースパスを指定して、resolveresolvePathを含むリゾルバ関数群を生成する。

  • これらは主にモジュールやプラグイン開発時に使い、Nuxtの設定に依存したパス解決を簡単にする。


いつ使うべきか?使わない方がよいケースは?

使うべきケース

  • モジュールやプラグイン開発時
    自作モジュール内で他のファイルやコンポーネントのパスを動的に解決したいとき。

  • エイリアスを含むパスを扱うとき
    Nuxtのalias設定を考慮して正しいパスを取得したい場合。

  • 拡張子が不明なファイルを解決したいとき
    .js.ts.vueなど複数の拡張子候補を試して最適なファイルを見つけたい場合。

  • 複数候補の中から存在するファイルを探す必要があるとき
    例えば、環境によって異なるファイル名を使い分けたい場合。

  • ベースパスを明示的に指定してパス解決を行いたいとき
    createResolverでリゾルバを作成し、モジュールの相対パスを簡単に解決したい場合。

使わない方がよいケース

  • 単純な静的パスの指定
    既に確定しているパスを使うだけなら、これらのユーティリティは不要。

  • クライアントサイドのランタイム処理でのパス解決
    これらはビルド時やサーバーサイドでのパス解決を想定しているため、クライアント側での動的解決には向かない。

  • パフォーマンスが極めて重要な処理で頻繁に呼び出す場合
    resolvePathfindPathは非同期処理を伴うため、過度な呼び出しはパフォーマンスに影響する可能性がある。


実務でよくあるユースケースとサンプルコード

1. モジュール内でプラグインのエントリポイントを解決する

モジュール開発時に、依存パッケージのエントリポイントを動的に解決し、プラグインとして登録する例です。

import { defineNuxtModule, resolvePath } from '@nuxt/kit'

export default defineNuxtModule({
  async setup() {
    const pluginPath = await resolvePath('@my-lib/plugin')
    // pluginPathを使ってプラグイン登録処理を行う
    console.log(`Plugin path resolved: ${pluginPath}`)
  }
})

2. 複数の候補ファイルから最初に存在するものを選択する

環境や設定によって異なるファイル名を使い分けたい場合に便利です。

import { defineNuxtModule, findPath } from '@nuxt/kit'
import { join } from 'pathe'

export default defineNuxtModule({
  async setup(_, nuxt) {
    const candidates = [
      join(nuxt.options.srcDir, 'App.vue'),
      join(nuxt.options.srcDir, 'app.vue'),
      join(nuxt.options.srcDir, 'Main.vue'),
    ]
    const mainComponent = await findPath(candidates, {}, 'file')
    if (mainComponent) {
      console.log(`Main component found at: ${mainComponent}`)
    } else {
      console.warn('No main component found among candidates.')
    }
  }
})

3. ベースパスを指定して相対パスを解決する

モジュールのファイル構成に依存したパス解決を簡潔に行えます。

import { defineNuxtModule, createResolver } from '@nuxt/kit'

export default defineNuxtModule({
  setup() {
    const resolver = createResolver(import.meta.url)
    const componentPath = resolver.resolve('./components/MyComponent.vue')
    console.log(`Component path: ${componentPath}`)
  }
})

よくある落とし穴・注意点

SSRとCSRの違いによる影響

これらのユーティリティは主にビルド時やサーバーサイドでのパス解決を目的としています。クライアントサイドのランタイムで使うと、ファイルシステムにアクセスできないためエラーになることがあります。クライアント側での動的パス解決は避け、ビルド時に解決しておくことが重要です。

Hydration(ハイドレーション)との関係

パス解決が不適切だと、サーバーとクライアントで異なるコンポーネントが読み込まれ、ハイドレーションエラーの原因になります。特に動的にパスを切り替える場合は、ビルド時に確定したパスを使うようにしましょう。

パフォーマンスへの配慮

resolvePathfindPathは非同期でファイルシステムを参照するため、頻繁に呼び出すとビルド時間が長くなる可能性があります。可能な限りキャッシュを活用したり、呼び出し回数を最小限に抑える工夫が必要です。

エイリアス設定の整合性

Nuxtのalias設定をカスタマイズしている場合、ユーティリティに渡すエイリアスオブジェクトが正しく反映されているか確認しましょう。誤ったエイリアスを渡すとパス解決に失敗します。


まとめ

Nuxtのパス解決ユーティリティは、モジュールやプラグイン開発においてファイルパスの解決を簡単かつ確実にする強力なツールです。resolvePathfindPathなどの関数を適切に使うことで、エイリアスや拡張子の違いを気にせずにパスを扱えます。

ただし、クライアントサイドでの使用や過度な非同期処理の多用は避け、ビルド時にパスを確定させることが重要です。実務では、これらのユーティリティを活用して開発効率を高めつつ、パフォーマンスやHydrationの問題に注意しながら設計しましょう。

Nuxtのパス解決ユーティリティは公式ドキュメントだけでなく、実際のモジュール開発コミュニティでも広く使われています。ぜひ積極的に活用して、より堅牢でメンテナブルなNuxtアプリケーションを作成してください。