brand logo

ドキュメント

カスタムルーティング

Nuxtでは、ルーティングはpagesディレクトリ内のファイル構造によって定義されます。しかし、内部でvue-routerを使用しているため、Nuxtはプロジェクトにカスタムルートを追加するためのいくつかの方法を提供しています。

カスタムルートの追加

Nuxtでは、ルーティングはpagesディレクトリ内のファイル構造によって定義されます。しかし、内部でvue-routerを使用しているため、Nuxtはプロジェクトにカスタムルートを追加するためのいくつかの方法を提供しています。

ルーター設定

ルーターオプションを使用して、スキャンされたルートを受け取り、カスタマイズされたルートを返す関数を使用してルートをオーバーライドまたは拡張することができます。

nullまたはundefinedを返すと、Nuxtはデフォルトのルートにフォールバックします(入力配列を変更するのに便利です)。

app/router.options.ts
import type { RouterConfig } from '@nuxt/schema'

export default {
  // https://router.vuejs.org/api/interfaces/routeroptions.html#routes
  routes: (_routes) => [
    {
      name: 'home',
      path: '/',
      component: () => import('~/pages/home.vue')
    }
  ],
} satisfies RouterConfig

Nuxtは、提供されたコンポーネントのdefinePageMetaで定義されたメタデータで、routes関数から返される新しいルートを拡張しません。それを実現したい場合は、ビルド時に呼び出されるpages:extendフックを使用する必要があります。

ページフック

pages:extend nuxtフックを使用して、スキャンされたルートからページを追加、変更、または削除することができます。

例えば、.tsファイルのルートを作成しないようにするには:

nuxt.config.ts
import type { NuxtPage } from '@nuxt/schema'

export default defineNuxtConfig({
  hooks: {
    'pages:extend' (pages) {
      // ルートを追加
      pages.push({
        name: 'profile',
        path: '/profile',
        file: '~/extra-pages/profile.vue'
      })

      // ルートを削除
      function removePagesMatching (pattern: RegExp, pages: NuxtPage[] = []) {
        const pagesToRemove: NuxtPage[] = []
        for (const page of pages) {
          if (page.file && pattern.test(page.file)) {
            pagesToRemove.push(page)
          } else {
            removePagesMatching(pattern, page.children)
          }
        }
        for (const page of pagesToRemove) {
          pages.splice(pages.indexOf(page), 1)
        }
      }
      removePagesMatching(/\.ts$/, pages)
    }
  }
})

Nuxtモジュール

特定の機能に関連する一連のページを追加する予定がある場合は、Nuxtモジュールを使用することをお勧めします。

Nuxtキットは、ルートを追加するためのいくつかの方法を提供しています:

ルーターオプション

vue-routerのオプションをカスタマイズすることに加えて、Nuxtはルーターをカスタマイズするための追加オプションを提供しています。

app/router.optionsの使用

これはルーターオプションを指定するための推奨方法です。

app/router.options.ts
import type { RouterConfig } from '@nuxt/schema'

export default {
} satisfies RouterConfig

pages:routerOptionsフック内にファイルを追加することで、さらにルーターオプションファイルを追加することが可能です。配列内の後の項目は、前の項目をオーバーライドします。

このフックにルーターオプションファイルを追加すると、ページベースのルーティングがオンになります。ただし、optionalが設定されている場合は、ページベースのルーティングがすでに有効になっている場合にのみ適用されます。

nuxt.config.ts
import { createResolver } from '@nuxt/kit'

export default defineNuxtConfig({
  hooks: {
    'pages:routerOptions' ({ files }) {
      const resolver = createResolver(import.meta.url)
      // ルートを追加
      files.push({
        path: resolver.resolve('./runtime/app/router-options'),
        optional: true
      })
    }
  }
})

nuxt.configの使用

注意: JSONシリアライズ可能なオプションのみが設定可能です:

  • linkActiveClass
  • linkExactActiveClass
  • end
  • sensitive
  • strict
  • hashMode
  • scrollBehaviorType
nuxt.config
export default defineNuxtConfig({
  router: {
    options: {}
  }
})

ハッシュモード (SPA)

hashMode 設定を使用してSPAモードでハッシュ履歴を有効にすることができます。このモードでは、ルーターは実際のURLの前にハッシュ文字(#)を使用します。これが有効になっている場合、URLはサーバーに送信されずSSRはサポートされません

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false,
  router: {
    options: {
      hashMode: true
    }
  }
})

ハッシュリンクのスクロール動作

ハッシュリンクのスクロール動作をカスタマイズすることができます。設定smoothに設定し、ハッシュリンク付きのページを読み込むと(例:https://example.com/blog/my-article#comments)、ブラウザがスムーズにこのアンカーにスクロールするのがわかります。

nuxt.config.ts
export default defineNuxtConfig({
  router: {
    options: {
      scrollBehaviorType: 'smooth'
    }
  }
})

カスタム履歴 (高度な設定)

ベースURLを受け取り、履歴モードを返す関数を使用して履歴モードをオーバーライドすることができます。nullまたはundefinedを返すと、Nuxtはデフォルトの履歴にフォールバックします。

app/router.options.ts
import type { RouterConfig } from '@nuxt/schema'
import { createMemoryHistory } from 'vue-router'

export default {
  // https://router.vuejs.org/api/interfaces/routeroptions.html
  history: base => import.meta.client ? createMemoryHistory(base) : null /* default */
} satisfies RouterConfig

tips

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

はじめに:Nuxtのカスタムルーティングがもたらす利便性

Nuxtはデフォルトでpagesディレクトリのファイル構造をもとにルーティングを自動生成しますが、実務ではこの自動生成だけでは対応しきれないケースが多々あります。例えば、動的にルートを追加したい、特定のファイルをルーティングから除外したい、あるいはルーターの挙動を細かく制御したい場合などです。

こうした課題を解決するために、Nuxtは内部で利用しているvue-routerの機能を活かしつつ、独自の拡張ポイントを提供しています。これにより、柔軟かつ保守性の高いルーティング設計が可能となり、複雑な要件にも対応できます。

本記事では、Nuxtのカスタムルーティングの概要から実務での具体的な使い方、注意点までを丁寧に解説します。


まず結論:Nuxtのカスタムルーティングの要点

  • ルートの追加・変更・削除はpages:extendフックで柔軟に実現可能
    既存の自動生成ルートに対して動的に操作できる。

  • app/router.optionsでvue-routerのルーターオプションをカスタマイズできる
    ルートの上書きや履歴モードの変更など高度な設定が可能。

  • NuxtモジュールやNuxtキットを使うと大規模なルート管理が効率化される
    複数ページをまとめて管理したい場合に有効。

  • SSRとCSRの違いに注意し、ハッシュモードなど一部設定はSSR非対応
    適切なモード選択がパフォーマンスやUXに影響。

  • ルーティングのカスタマイズは保守性を考慮し、必要最低限に留めるのが望ましい
    過度なカスタマイズはトラブルの元。


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

使うべきケース

  • 標準のpagesディレクトリ構造だけでは対応できないルーティング要件がある場合
    例:特定のファイルをルーティングから除外したい、動的にルートを追加したい。

  • ルーターの履歴モードやスクロール動作など細かい挙動を制御したい場合
    例:SPAモードでハッシュモードを使いたい、スクロールをスムーズにしたい。

  • 複数の関連ページをまとめて管理するNuxtモジュールを作成・利用する場合
    大規模プロジェクトでのルート管理に便利。

使わない方がよいケース

  • 単純なページ構成で、pagesディレクトリの自動生成ルートで十分な場合
    余計なカスタマイズは複雑化の原因。

  • SSRが必要なプロジェクトで、ハッシュモードなどSSR非対応の設定を使いたい場合
    SSRが無効になるため注意。

  • ルーティングの挙動を理解せずに安易にカスタマイズを行う場合
    予期せぬ動作やパフォーマンス低下のリスク。


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

1. 特定のファイルをルーティングから除外する

TypeScriptファイル(.ts)をページとして扱いたくない場合、pages:extendフックで除外できます。

export default defineNuxtConfig({
  hooks: {
    'pages:extend'(pages) {
      function removePagesMatching(pattern: RegExp, pages: any[] = []) {
        const pagesToRemove = []
        for (const page of pages) {
          if (page.file && pattern.test(page.file)) {
            pagesToRemove.push(page)
          } else {
            removePagesMatching(pattern, page.children)
          }
        }
        for (const page of pagesToRemove) {
          pages.splice(pages.indexOf(page), 1)
        }
      }
      removePagesMatching(/\.ts$/, pages)
    }
  }
})

2. 動的にルートを追加する

外部のVueファイルをルートとして追加したい場合もpages:extendが便利です。

export default defineNuxtConfig({
  hooks: {
    'pages:extend'(pages) {
      pages.push({
        name: 'profile',
        path: '/profile',
        file: '~/extra-pages/profile.vue'
      })
    }
  }
})

3. ルーターの履歴モードをカスタマイズする

SPAでメモリ履歴を使いたい場合、app/router.options.tsで設定します。

import type { RouterConfig } from '@nuxt/schema'
import { createMemoryHistory } from 'vue-router'

export default {
  history: base => import.meta.client ? createMemoryHistory(base) : null
} satisfies RouterConfig

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

SSRとCSRの違いに注意

  • ハッシュモードはSSR非対応
    hashMode: trueを設定すると、URLのハッシュ部分がサーバーに送信されず、SSRが無効になります。SSRが必要な場合は使わないようにしましょう。

Hydrationエラーのリスク

  • ルートの動的追加や削除を行う際、サーバーとクライアントでルート構成が異なるとHydrationエラーが発生します。
    ルートの変更はビルド時に確定させるか、クライアント専用の処理に限定することが重要です。

パフォーマンスへの影響

  • ルート数が増えすぎると、初期ロード時のルーティング処理に影響が出ることがあります。
    不要なルートは極力除外し、必要なルートのみを追加する設計が望ましいです。

ルートメタ情報の扱い

  • routes関数で返したカスタムルートは、ページコンポーネントのdefinePageMetaで定義したメタ情報が自動的に反映されません。
    メタ情報を活用したい場合はpages:extendフックでルートを操作する方法が推奨されます。

まとめ

Nuxtのカスタムルーティング機能は、標準のページベースルーティングの枠を超えた柔軟なルート管理を可能にします。pages:extendフックやapp/router.optionsを活用することで、実務でよくある複雑なルーティング要件にも対応可能です。

ただし、SSRとの整合性やパフォーマンス面の注意が必要なため、カスタマイズは必要最低限に留め、Nuxtの標準機能を最大限活用することが望ましいです。適切に使いこなせば、保守性と拡張性の高いNuxtアプリケーションを構築できます。


カスタムルーティングを導入する際は、まずは小さな変更から始めて動作を確認し、問題がなければ段階的に拡張していくことをおすすめします。