server
server/ ディレクトリは、アプリケーションに API とサーバーハンドラーを登録するために使用されます。
Nuxt はこれらのディレクトリ内のファイルを自動的にスキャンし、ホットモジュールリプレースメント (HMR) サポート付きで API とサーバーハンドラーを登録します。
-| server/
---| api/
-----| hello.ts # /api/hello
---| routes/
-----| bonjour.ts # /bonjour
---| middleware/
-----| log.ts # すべてのリクエストをログ
各ファイルは defineEventHandler()
または eventHandler()
(エイリアス)で定義されたデフォルト関数をエクスポートする必要があります。
ハンドラーは直接 JSON データを返すか、Promise
を返すか、event.node.res.end()
を使用してレスポンスを送信することができます。
export default defineEventHandler((event) => {
return {
hello: 'world'
}
})
この API は、ページやコンポーネントでユニバーサルに呼び出すことができます:
<script setup lang="ts">
const { data } = await useFetch('/api/hello')
</script>
<template>
<pre>{{ data }}</pre>
</template>
サーバールート
~/server/api
内のファイルは、自動的にルートに /api
がプレフィックスされます。
/api
プレフィックスなしでサーバールートを追加するには、~/server/routes
ディレクトリに配置します。
例:
export default defineEventHandler(() => 'Hello World!')
上記の例では、/hello
ルートは http://localhost:3000/hello でアクセス可能になります。
現在、サーバールートは pages のように動的ルートの完全な機能をサポートしていないことに注意してください。
サーバーミドルウェア
Nuxt は ~/server/middleware
内のファイルを自動的に読み込み、プロジェクトのサーバーミドルウェアを作成します。
ミドルウェアハンドラーは、ヘッダーの追加やチェック、リクエストのログ、イベントのリクエストオブジェクトの拡張を行うために、他のサーバールートの前にすべてのリクエストで実行されます。
ミドルウェアハンドラーは何も返さず(リクエストを閉じたり応答したりせず)、リクエストコンテキストを検査または拡張するか、エラーをスローするだけにするべきです。
例:
export default defineEventHandler((event) => {
console.log('New request: ' + getRequestURL(event))
})
export default defineEventHandler((event) => {
event.context.auth = { user: 123 }
})
サーバープラグイン
Nuxt は ~/server/plugins
ディレクトリ内のファイルを自動的に読み込み、Nitro プラグインとして登録します。これにより、Nitro のランタイム動作を拡張し、ライフサイクルイベントにフックすることができます。
例:
export default defineNitroPlugin((nitroApp) => {
console.log('Nitro plugin', nitroApp)
})
サーバーユーティリティ
サーバールートは h3js/h3 によって動作しており、便利なヘルパーセットが付属しています。
こちらも参照 利用可能な H3 リクエストヘルパー~/server/utils
ディレクトリ内に独自のヘルパーを追加することもできます。
例えば、オリジナルのハンドラーをラップし、最終的なレスポンスを返す前に追加の操作を行うカスタムハンドラーユーティリティを定義できます。
例:
import type { EventHandler, EventHandlerRequest } from 'h3'
export const defineWrappedResponseHandler = <T extends EventHandlerRequest, D> (
handler: EventHandler<T, D>
): EventHandler<T, D> =>
defineEventHandler<T>(async event => {
try {
// ルートハンドラーの前に何かを行う
const response = await handler(event)
// ルートハンドラーの後に何かを行う
return { response }
} catch (err) {
// エラーハンドリング
return { err }
}
})
サーバータイプ
この機能は Nuxt >= 3.5 から利用可能です
IDE 内で 'nitro' と 'vue' からの自動インポートを明確にするために、次の内容で ~/server/tsconfig.json
を追加できます:
{
"extends": "../.nuxt/tsconfig.server.json"
}
現在、これらの値は型チェック時(nuxt typecheck
)には尊重されませんが、IDE でより良い型ヒントを得ることができます。
レシピ
ルートパラメータ
サーバールートは、ファイル名にブラケットで囲まれた動的パラメータを使用し、event.context.params
を介してアクセスできます。
export default defineEventHandler((event) => {
const name = getRouterParam(event, 'name')
return `Hello, ${name}!`
})
代わりに、getValidatedRouterParams
を Zod などのスキーマバリデーターと共に使用して、ランタイムと型の安全性を確保します。
この API は /api/hello/nuxt
でユニバーサルに呼び出すことができ、Hello, nuxt!
を取得します。
HTTP メソッドのマッチング
ファイル名は .get
, .post
, .put
, .delete
, ... でサフィックスを付けて、リクエストの HTTP メソッド にマッチさせることができます。
export default defineEventHandler(() => 'Test get handler')
export default defineEventHandler(() => 'Test post handler')
上記の例では、/test
をフェッチすると:
- GET メソッド:
Test get handler
を返す - POST メソッド:
Test post handler
を返す - その他のメソッド: 405 エラーを返す
ディレクトリ内で index.[method].ts
を使用してコードを異なる構造にすることもできます。これは API 名前空間を作成するのに便利です。
export default defineEventHandler((event) => {
// `api/foo` エンドポイントの GET リクエストを処理
})
キャッチオールルート
キャッチオールルートは、フォールバックルートの処理に役立ちます。
例えば、~/server/api/foo/[...].ts
という名前のファイルを作成すると、/api/foo/bar/baz
のように、どのルートハンドラーにも一致しないすべてのリクエストに対してキャッチオールルートが登録されます。
export default defineEventHandler((event) => {
// event.context.path でルートパスを取得: '/api/foo/bar/baz'
// event.context.params._ でルートセグメントを取得: 'bar/baz'
return `Default foo handler`
})
キャッチオールルートに名前を付けるには、~/server/api/foo/[...slug].ts
を使用し、event.context.params.slug
を介してアクセスします。
export default defineEventHandler((event) => {
// event.context.params.slug でルートセグメントを取得: 'bar/baz'
return `Default foo handler`
})
ボディ処理
export default defineEventHandler(async (event) => {
const body = await readBody(event)
return { body }
})
代わりに、readValidatedBody
を Zod などのスキーマバリデーターと共に使用して、ランタイムと型の安全性を確保します。
この API は次のようにユニバーサルに呼び出すことができます:
async function submit() {
const { body } = await $fetch('/api/submit', {
method: 'post',
body: { test: 123 }
})
}
ファイル名で submit.post.ts
を使用しているのは、リクエストボディを受け入れることができる POST
メソッドのリクエストと一致させるためだけです。GET リクエスト内で readBody
を使用すると、405 Method Not Allowed
HTTP エラーがスローされます。
クエリパラメータ
サンプルクエリ /api/query?foo=bar&baz=qux
export default defineEventHandler((event) => {
const query = getQuery(event)
return { a: query.foo, b: query.baz }
})
代わりに、getValidatedQuery
を Zod などのスキーマバリデーターと共に使用して、ランタイムと型の安全性を確保します。
エラーハンドリング
エラーがスローされない場合、200 OK
のステータスコードが返されます。
キャッチされないエラーは 500 Internal Server Error
HTTP エラーを返します。
他のエラーコードを返すには、createError
を使用して例外をスローします:
export default defineEventHandler((event) => {
const id = parseInt(event.context.params.id) as number
if (!Number.isInteger(id)) {
throw createError({
statusCode: 400,
statusMessage: 'ID should be an integer',
})
}
return 'All good'
})
ステータスコード
他のステータスコードを返すには、setResponseStatus
ユーティリティを使用します。
例えば、202 Accepted
を返すには
export default defineEventHandler((event) => {
setResponseStatus(event, 202)
})
ランタイム設定
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig(event)
const repo = await $fetch('https://api.github.com/repos/nuxt/nuxt', {
headers: {
Authorization: `token ${config.githubToken}`
}
})
return repo
})
サーバールートのランタイムで 環境変数 によって上書きされたランタイム設定を取得するために、useRuntimeConfig
に event
を引数として渡すことをお勧めしますが、これはオプションです。
リクエストクッキー
export default defineEventHandler((event) => {
const cookies = parseCookies(event)
return { cookies }
})
コンテキストとヘッダーの転送
デフォルトでは、サーバールートでフェッチリクエストを行う際に、受信リクエストのヘッダーやリクエストコンテキストは転送されません。サーバールートでフェッチリクエストを行う際に、リクエストコンテキストとヘッダーを転送するには、event.$fetch
を使用します。
export default defineEventHandler((event) => {
return event.$fetch('/api/forwarded')
})
転送されるべきでない ヘッダーはリクエストに含まれません。これらのヘッダーには、例えば:
transfer-encoding
, connection
, keep-alive
, upgrade
, expect
, host
, accept
レスポンス後の Promise の待機
サーバーリクエストを処理する際、クライアントへのレスポンスをブロックしない非同期タスク(例えば、キャッシングやログ記録)を実行する必要があるかもしれません。event.waitUntil
を使用して、バックグラウンドで Promise を待機し、レスポンスを遅延させずにタスクを完了させることができます。
event.waitUntil
メソッドは、ハンドラーが終了する前に待機する Promise を受け入れ、レスポンスが送信された直後にサーバーがハンドラーを終了する場合でもタスクが完了することを保証します。これは、ランタイムプロバイダーと統合して、レスポンス送信後の非同期操作を処理するためのネイティブ機能を活用します。
const timeConsumingBackgroundTask = async () => {
await new Promise((resolve) => setTimeout(resolve, 1000))
};
export default eventHandler((event) => {
// レスポンスをブロックせずにバックグラウンドタスクをスケジュール
event.waitUntil(timeConsumingBackgroundTask())
// クライアントに即座にレスポンスを送信
return 'done'
});
高度な使用法
Nitro 設定
nuxt.config
の nitro
キーを使用して、Nitro 設定 を直接設定できます。
これは高度なオプションです。カスタム設定は、Nitro が Nuxt の semver-minor バージョンでアップグレードされるときに、設定インターフェースが変更される可能性があるため、プロダクションデプロイメントに影響を与える可能性があります。
export default defineNuxtConfig({
// https://nitro.build/config
nitro: {}
})
ネストされたルーター
import { createRouter, defineEventHandler, useBase } from 'h3'
const router = createRouter()
router.get('/test', defineEventHandler(() => 'Hello World'))
export default useBase('/api/hello', router.handler)
ストリームの送信
これは実験的な機能であり、すべての環境で利用可能です。
import fs from 'node:fs'
import { sendStream } from 'h3'
export default defineEventHandler((event) => {
return sendStream(event, fs.createReadStream('/path/to/file'))
})
リダイレクトの送信
export default defineEventHandler(async (event) => {
await sendRedirect(event, '/path/redirect/to', 302)
})
レガシーハンドラーまたはミドルウェア
export default fromNodeMiddleware((req, res) => {
res.end('Legacy handler')
})
レガシーサポートは h3js/h3 を使用して可能ですが、できるだけレガシーハンドラーを避けることをお勧めします。
export default fromNodeMiddleware((req, res, next) => {
console.log('Legacy middleware')
next()
})
next()
コールバックを async
または Promise
を返すレガシーミドルウェアと組み合わせないでください。
サーバーストレージ
Nitro はクロスプラットフォームのストレージレイヤーを提供します。追加のストレージマウントポイントを設定するには、nitro.storage
または サーバープラグイン を使用できます。
Redis ストレージを追加する例:
nitro.storage
を使用:
export default defineNuxtConfig({
nitro: {
storage: {
redis: {
driver: 'redis',
/* redis コネクタオプション */
port: 6379, // Redis ポート
host: "127.0.0.1", // Redis ホスト
username: "", // Redis >= 6 が必要
password: "",
db: 0, // デフォルトは 0
tls: {} // tls/ssl
}
}
}
})
次に、API ハンドラーで:
export default defineEventHandler(async (event) => {
// すべてのキーをリストする
const keys = await useStorage('redis').getKeys()
// キーを設定する
await useStorage('redis').setItem('foo', 'bar')
// キーを削除する
await useStorage('redis').removeItem('foo')
return {}
})
代わりに、サーバープラグインとランタイム設定を使用してストレージマウントポイントを作成することもできます:
import redisDriver from 'unstorage/drivers/redis'
export default defineNitroPlugin(() => {
const storage = useStorage()
// ランタイム設定や他のソースから動的に資格情報を渡す
const driver = redisDriver({
base: 'redis',
host: useRuntimeConfig().redis.host,
port: useRuntimeConfig().redis.port,
/* 他の redis コネクタオプション */
})
// ドライバーをマウント
storage.mount('redis', driver)
})
※このページは Nuxt.js 公式ドキュメントの翻訳ページ(非公式)です。
公式ドキュメントの該当ページはこちら:
https://nuxt.com/docs/3.x/guide/directory-structure/server