brand logo

ドキュメント

Nitro

Nuxt Kitは、Nitroを扱うためのユーティリティを提供します。これらの関数を使用して、サーバーハンドラー、プラグイン、プリレンダールートを追加できます。

Nitroは、超高速なウェブサーバーを構築するためのオープンソースのTypeScriptフレームワークです。NuxtはそのサーバーエンジンとしてNitroを使用しています。useNitroを使用してNitroインスタンスにアクセスし、addServerHandlerでサーバーハンドラーを追加し、addDevServerHandlerで開発モードでのみ使用されるサーバーハンドラーを追加し、addServerPluginでNitroのランタイム動作を拡張するプラグインを追加し、addPrerenderRoutesでNitroによってプリレンダーされるルートを追加できます。

addServerHandler

Nitroサーバーハンドラーを追加します。サーバーミドルウェアやカスタムルートを作成したい場合に使用します。

使用法

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

export default defineNuxtModule({
  setup(options) {
    const { resolve } = createResolver(import.meta.url)

    addServerHandler({
      route: '/robots.txt',
      handler: resolve('./runtime/robots.get')
    })
  }
})

function addServerHandler (handler: NitroEventHandler): void

パラメータ

handler: 以下のプロパティを持つハンドラーオブジェクト:

プロパティ必須説明
handlerstringtrueイベントハンドラーへのパス。
routestringfalseパスプレフィックスまたはルート。空文字列が使用された場合、ミドルウェアとして使用されます。
middlewarebooleanfalseこれはミドルウェアハンドラーであることを指定します。ミドルウェアはすべてのルートで呼び出され、通常は次のハンドラーに渡すために何も返さないべきです。
lazybooleanfalseハンドラーをインポートするために遅延読み込みを使用します。これは、ハンドラーをオンデマンドでのみ読み込みたい場合に便利です。
methodstringfalseルーターメソッドマッチャー。ハンドラー名にメソッド名が含まれている場合、それがデフォルト値として使用されます。

基本的な使用法

addServerHandlerを使用して、モジュールからサーバーハンドラーを追加できます。

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

export default defineNuxtModule({
  setup(options) {
    const { resolve } = createResolver(import.meta.url)

    addServerHandler({
      route: '/robots.txt',
      handler: resolve('./runtime/robots.get')
    })
  }
})

/robots.txtにアクセスすると、次のレスポンスが返されます:

User-agent: *
Disallow: /

addDevServerHandler

開発モードでのみ使用されるNitroサーバーハンドラーを追加します。このハンドラーは本番ビルドから除外されます。

使用法

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

export default defineNuxtModule({
  setup() {
    addDevServerHandler({
      handler: defineEventHandler(() => {
        return {
          body: `Response generated at ${new Date().toISOString()}`
        }
      }),
      route: '/_handler'
    })
  }
})

// @errors: 2391
import type { NitroDevEventHandler } from 'nitropack'
// ---cut---
function addDevServerHandler (handler: NitroDevEventHandler): void

パラメータ

handler: 以下のプロパティを持つハンドラーオブジェクト:

プロパティ必須説明
handlerEventHandlertrueイベントハンドラー。
routestringfalseパスプレフィックスまたはルート。空文字列が使用された場合、ミドルウェアとして使用されます。

基本的な使用法

場合によっては、開発目的で特定のサーバーハンドラーを作成したいことがあります。例えば、Tailwindの設定ビューアーなどです。

import { joinURL } from 'ufo'
import { defineNuxtModule, addDevServerHandler } from '@nuxt/kit'

export default defineNuxtModule({
  async setup(options, nuxt) {
    const route = joinURL(nuxt.options.app?.baseURL, '/_tailwind')

    // @ts-ignore
    const createServer = await import('tailwind-config-viewer/server/index.js').then(r => r.default || r) as any
    const viewerDevMiddleware = createServer({ tailwindConfigProvider: () => options, routerPrefix: route }).asMiddleware()

    addDevServerHandler({ route, handler: viewerDevMiddleware })
  }
})

useNitro

Nitroインスタンスを返します。

useNitro()readyフックの後でのみ呼び出すことができます。

Nitroインスタンスの設定への変更は適用されません。

使用法

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

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

    nuxt.hook('ready', () => {
      const nitro = useNitro()
      // Nitroインスタンスで何かを行う
    })
  }
})

function useNitro (): Nitro

addServerPlugin

Nitroのランタイム動作を拡張するプラグインを追加します。

Nitroプラグインについての詳細はNitroドキュメントを参照してください。

使用法

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

export default defineNuxtModule({
  setup() {
    const { resolve } = createResolver(import.meta.url)
    addServerPlugin(resolve('./runtime/plugin.ts'))
  }
})

function addServerPlugin (plugin: string): void

パラメータ

プロパティ必須説明
pluginstringtrueプラグインへのパス。プラグインは、Nitroインスタンスを引数として受け取るデフォルト関数をエクスポートする必要があります。

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

export default defineNuxtModule({
  setup() {
    const { resolve } = createResolver(import.meta.url)
    addServerPlugin(resolve('./runtime/plugin.ts'))
  }
})

addPrerenderRoutes

Nitroにプリレンダーされるルートを追加します。

使用法

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

export default defineNuxtModule({
  meta: {
    name: 'nuxt-sitemap',
    configKey: 'sitemap',
  },
  defaults: {
    sitemapUrl: '/sitemap.xml',
    prerender: true,
  },
  setup(options) {
    if (options.prerender) {
      addPrerenderRoutes(options.sitemapUrl)
    }
  }
})

function addPrerenderRoutes (routes: string | string[]): void

パラメータ

プロパティ必須説明
routesstring | string[]{lang="ts"}trueプリレンダーするルートまたはルートの配列。

addServerImportsDir

Nitroによって自動インポートされるディレクトリを追加します。

使用法

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

export default defineNuxtModule({
  meta: {
    name: 'my-module',
    configKey: 'myModule',
  },
  setup(options) {
    const { resolve } = createResolver(import.meta.url)
    addServerImportsDir(resolve('./runtime/server/composables'))
  }
})

function addServerImportsDir (dirs: string | string[], opts: { prepend?: boolean }): void

パラメータ

プロパティ必須説明
dirsstring | string[]{lang="ts"}trueNitroによってスキャンされるディレクトリまたはディレクトリの配列。
opts{ prepend?: boolean }falseインポートディレクトリのオプション。prependtrueの場合、ディレクトリはスキャンリストの先頭に追加されます。

addServerImportsDirを使用して、Nitroによってスキャンされるディレクトリを追加できます。これは、カスタムサーバーディレクトリから関数を自動インポートしたい場合に便利です。

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

export default defineNuxtModule({
  meta: {
    name: 'my-module',
    configKey: 'myModule',
  },
  setup(options) {
    const { resolve } = createResolver(import.meta.url)
    addServerImportsDir(resolve('./runtime/server/composables'))
  }
})

その後、サーバーコードでuseApiSecret関数を使用できます:

runtime/server/api/hello.ts
const useApiSecret = (): string => ''
// ---cut---
export default defineEventHandler(() => {
  const apiSecret = useApiSecret()
  // apiSecretを使用して何かを行う
})

addServerScanDir

Nitroによってスキャンされるディレクトリを追加します。サブディレクトリをチェックし、~/serverフォルダと同様に登録されます。

~/server/api~/server/routes~/server/middleware~/server/utilsのみがスキャンされます。

使用法

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

export default defineNuxtModule({
  meta: {
    name: 'my-module',
    configKey: 'myModule',
  },
  setup(options) {
    const { resolve } = createResolver(import.meta.url)
    addServerScanDir(resolve('./runtime/server'))
  }
})

function addServerScanDir (dirs: string | string[], opts: { prepend?: boolean }): void

パラメータ

プロパティ必須説明
dirsstring | string[]{lang="ts"}trueNitroによってサーバーディレクトリとしてスキャンされるディレクトリまたはディレクトリの配列。
opts{ prepend?: boolean }falseインポートディレクトリのオプション。prependtrueの場合、ディレクトリはスキャンリストの先頭に追加されます。

addServerScanDirを使用して、Nitroによってスキャンされるディレクトリを追加できます。これは、カスタムサーバーディレクトリを追加したい場合に便利です。

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

export default defineNuxtModule({
  meta: {
    name: 'my-module',
    configKey: 'myModule',
  },
  setup(options) {
    const { resolve } = createResolver(import.meta.url)
    addServerScanDir(resolve('./runtime/server'))
  }
})

その後、サーバーコードでhello関数を使用できます。

runtime/server/api/hello.ts
function hello() {
  return 'Hello from server utils!'
}
// ---cut---
export default defineEventHandler(() => {
  return hello() // Hello from server utils!
})

tips

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

Nuxt Nitroのサーバーハンドラーとプラグイン活用ガイド

Nuxt 3のサーバーエンジンとして採用されているNitroは、高速かつ柔軟なサーバー構築を可能にするTypeScriptベースのフレームワークです。Nuxt公式ドキュメントでは基本的な使い方が紹介されていますが、本記事では実務での活用を念頭に置き、より詳しくNitroのサーバーハンドラーやプラグインの使いどころ、注意点を解説します。


1. イントロダクション:Nitroで何が嬉しいのか?

Nitroを使うことで、Nuxtアプリケーションに以下のようなメリットがあります。

  • 高速なサーバーレスポンスを実現しつつ、柔軟にカスタムAPIやミドルウェアを追加可能
  • 開発モードと本番モードで異なるサーバーハンドラーを使い分けられるため、開発効率が向上
  • Nitroプラグインでサーバーのリクエスト・レスポンス処理を拡張できる
  • プリレンダー対象のルートを簡単に追加し、SEOやパフォーマンスを改善できる

これらは、Nuxtのサーバーサイドレンダリング(SSR)やAPI構築をより強力にサポートします。


2. まず結論:Nitroの主要ポイント

  • addServerHandlerでカスタムサーバーハンドラー(APIエンドポイントやミドルウェア)を追加できる
  • addDevServerHandlerは開発時のみ有効なハンドラーを登録し、本番ビルドには含まれない
  • addServerPluginでNitroのランタイム動作をフックし、リクエストやレスポンスの処理を拡張可能
  • addPrerenderRoutesで静的プリレンダー対象のルートを追加し、SEO対策や初期表示高速化に貢献
  • useNitroでNitroインスタンスにアクセスできるが、readyフック以降での呼び出しが必須

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

使うべきケース

  • APIエンドポイントをNuxtモジュールやプラグイン内で追加したいとき
    例:独自の認証APIやWebhook受け口を作成する場合

  • 開発時のみの特別なサーバーハンドラーを用意したいとき
    例:Tailwind CSSの設定ビューアーなど、開発補助ツールのためのサーバー処理

  • リクエスト・レスポンスの共通処理をカスタマイズしたいとき
    例:ログ記録やレスポンスヘッダーの追加など

  • 静的プリレンダーで生成するルートを動的に追加したいとき
    例:サイトマップ生成や動的ページのプリレンダー指定

避けたほうがよいケース

  • 単純なAPI処理をページのサーバーAPIディレクトリで完結できる場合
    余計に複雑化する恐れがあるため、まずは標準のAPIディレクトリを検討

  • クライアントサイドのみで完結する処理
    Nitroはサーバー側の処理に特化しているため、クライアント処理はVueコンポーネントやComposableで実装

  • Nitroのreadyフック前にuseNitroを呼び出すこと
    Nitroインスタンスが未初期化のためエラーになる


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

ユースケース1:カスタムAPIエンドポイントの追加

Nuxtモジュール内でaddServerHandlerを使い、独自のAPIを追加します。

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

export default defineNuxtModule({
  setup() {
    const { resolve } = createResolver(import.meta.url)

    addServerHandler({
      route: '/api/hello',
      handler: resolve('./runtime/api/hello.get')
    })
  }
})

runtime/api/hello.get.ts:

export default defineEventHandler(() => {
  return { message: 'Hello from custom API!' }
})

ユースケース2:開発時のみのサーバーハンドラー追加

開発モード限定のAPIをaddDevServerHandlerで登録し、本番ビルドに含めません。

import { defineNuxtModule, addDevServerHandler } from '@nuxt/kit'
import { defineEventHandler } from 'h3'

export default defineNuxtModule({
  setup() {
    addDevServerHandler({
      route: '/_dev/time',
      handler: defineEventHandler(() => {
        return { now: new Date().toISOString() }
      })
    })
  }
})

ユースケース3:Nitroプラグインでリクエストログを追加

addServerPluginでNitroのリクエスト処理にフックし、ログを出力します。

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

export default defineNuxtModule({
  setup() {
    const { resolve } = createResolver(import.meta.url)
    addServerPlugin(resolve('./runtime/nitro-logger'))
  }
})

runtime/nitro-logger.ts:

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('request', (event) => {
    console.log(`[Request] ${event.req.method} ${event.path}`)
  })
})

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

SSRとCSRの境界

  • サーバーハンドラーはサーバー側でのみ動作し、クライアント側では呼び出せません。API呼び出しはHTTP経由で行う必要があります。

Hydrationの影響

  • サーバーで生成したレスポンスとクライアントの状態が不整合になるとHydrationエラーが発生する可能性があります。APIレスポンスは一貫性を保つよう注意してください。

パフォーマンス面の注意

  • addServerHandlerで大量のミドルウェアを登録するとリクエスト処理が遅くなることがあります。必要最低限のハンドラーに絞りましょう。

  • lazyオプションを活用し、ハンドラーの遅延読み込みを行うことで初期起動の負荷を軽減できます。

useNitroの呼び出しタイミング

  • Nitroインスタンスはreadyフック以降でしか安全に取得できません。早すぎる呼び出しはエラーの原因となるため注意してください。

6. まとめ

NitroはNuxtのサーバー機能を強力に拡張する基盤であり、addServerHandleraddDevServerHandleraddServerPluginなどのAPIを使いこなすことで、柔軟かつ効率的なサーバーサイド開発が可能になります。開発時と本番環境での使い分けやパフォーマンス面の配慮を忘れずに、実務に即した設計を心がけましょう。


Nitroの詳細なプラグイン開発やAPI仕様については、公式Nitroドキュメント(https://nitro.build/guide/plugins)もあわせて参照すると理解が深まります。


title: 'NuxtのaddServerScanDirでサーバーディレクトリを柔軟に拡張する方法' description: 'NuxtのNitroサーバースキャン機能を拡張するaddServerScanDirの使い方と実務での活用例、注意点を詳しく解説します。カスタムサーバーディレクトリの追加やモジュール開発に役立つ知識を初心者から中級者向けに丁寧に紹介。'

NuxtのaddServerScanDirとは?〜サーバーディレクトリの拡張で開発効率アップ〜

Nuxt 3では、Nitroがサーバーサイドのコードを自動的にスキャンしてビルドに組み込みます。通常は~/server以下の特定のサブディレクトリ(apiroutesなど)が対象ですが、プロジェクトやモジュールの要件によっては、これ以外の場所にサーバーコードを置きたい場合があります。そんなときに役立つのがaddServerScanDirです。

この関数を使うと、Nitroがスキャンするサーバーディレクトリを追加でき、カスタムのサーバーコードを柔軟に管理可能になります。結果として、モジュール開発や大規模プロジェクトでのコード分割がしやすくなり、開発効率や保守性が向上します。


まず結論:addServerScanDirのポイント

  • Nitroのサーバースキャン対象ディレクトリを追加できる
    デフォルトの~/server以外の場所もサーバーコードとして認識させられる。

  • 複数ディレクトリの追加やスキャン順序の制御が可能
    配列で複数指定でき、prependオプションで優先度を調整できる。

  • 主にモジュール開発やカスタムサーバー構成で使う
    プロジェクトの構造を柔軟に設計したい場合に有効。

  • スキャン対象はapiroutesなど特定のサブディレクトリに限定される
    無制限ではないため、構造は公式仕様に準拠する必要がある。


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

使うべきケース

  • モジュールやプラグインで独自のサーバーコードを持ちたいとき
    例えば、共通のAPI処理やミドルウェアをモジュール内にまとめたい場合。

  • プロジェクトのサーバーコードを複数の場所に分割したいとき
    大規模プロジェクトで機能ごとにサーバーコードを分けて管理したい場合。

  • 既存のサーバーディレクトリ構造を変更せずに追加機能を実装したいとき
    既存の~/serverを汚さずに拡張したい場合。

使わない方がよいケース

  • 単純なプロジェクトで~/serverだけで十分な場合
    余計な設定を増やす必要はなく、シンプルに保つ方が管理しやすい。

  • スキャン対象外のディレクトリにサーバーコードを置きたい場合
    addServerScanDirはあくまでNitroのスキャン対象を追加するだけで、任意の場所を自由に使えるわけではない。

  • クライアント専用コードやユーティリティのみの場合
    サーバーコードではないため、スキャン対象に含める意味がない。


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

1. モジュール内に独自のサーバーAPIを持たせる

モジュール開発時に、runtime/server配下にAPIを実装し、addServerScanDirでスキャン対象に追加します。

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

export default defineNuxtModule({
  meta: {
    name: 'my-custom-module',
    configKey: 'myCustomModule',
  },
  setup() {
    const { resolve } = createResolver(import.meta.url)
    addServerScanDir(resolve('./runtime/server'))
  }
})

この設定により、モジュール内のruntime/server/apiに置いたAPIエンドポイントがNuxtアプリの一部として動作します。


2. プロジェクトで機能ごとにサーバーコードを分割

例えば、~/serverとは別に~/custom-serverディレクトリを作り、そこにAPIやミドルウェアを置きたい場合。

import { addServerScanDir } from '@nuxt/kit'
import { resolve } from 'path'

addServerScanDir(resolve('./custom-server'))

こうすることで、custom-server/api以下のファイルもサーバーAPIとして認識されます。


3. スキャン順序を制御して優先度を変更

複数のサーバーディレクトリを追加する際、prepend: trueを指定するとスキャンリストの先頭に追加され、優先度が上がります。

addServerScanDir(resolve('./priority-server'), { prepend: true })
addServerScanDir(resolve('./normal-server'))

これにより、priority-serverのAPIが優先的に解決されます。


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

1. スキャン対象は限定的

addServerScanDirで追加できるのは、apiroutesmiddlewareutilsなど、Nitroが認識する特定のサブディレクトリのみです。これ以外のディレクトリはスキャンされません。


2. SSRとHydrationの影響

サーバーコードはSSR時に実行されるため、クライアント側でのHydrationに影響しませんが、APIのレスポンスやミドルウェアの挙動が変わると、クライアントの動作にも影響が出る可能性があります。追加したサーバーディレクトリのコードは十分にテストしましょう。


3. パフォーマンスへの配慮

スキャン対象ディレクトリを増やしすぎると、ビルド時間やサーバー起動時間が長くなることがあります。必要最低限のディレクトリだけを追加し、不要なファイルは含めないようにしましょう。


4. モジュールの依存関係に注意

モジュール内でaddServerScanDirを使う場合、依存関係の解決やパスの指定ミスに注意してください。createResolverを使って絶対パスを正しく解決するのが安全です。


まとめ

addServerScanDirは、NuxtのNitroサーバースキャン機能を拡張し、カスタムサーバーディレクトリを柔軟に追加できる強力なAPIです。モジュール開発や大規模プロジェクトでのコード分割に役立ちますが、スキャン対象の制限やパフォーマンスへの影響を理解した上で使うことが重要です。

適切に活用すれば、Nuxtのサーバーサイド開発の自由度が大きく広がり、保守性や拡張性の高いアプリケーション構築が可能になります。ぜひ実務での活用を検討してみてください。


モジュール開発時はcreateResolverでパスを解決し、addServerScanDirに渡すのがベストプラクティスです。これにより環境依存のパス問題を防げます。