Nuxt 3ミドルウェアの探索：包括的な概要

Nuxt.jsを使用することで、Vue.jsフレームワークでのウェブアプリケーションの開発をより簡単にすることができます。その中でも、Nuxt.jsのミドルウェアは、ページまたはページグループをレンダリングする前に実行されるカスタム関数で、認証のチェックや、サーバーレスポンスの変更、クッキーのアクセスなど、様々な処理が可能です。今回は、Nuxt.jsのミドルウェアの特徴と使い方について、包括的な概要を紹介します。

## レンダリングモード

ミドルウェアについて詳しく話す前に、Nuxt.jsのレンダリングモードについて説明しましょう。

クライアントサイドレンダリング（Client-side Only Rendering）は、Vue.jsアプリケーションがブラウザ（またはクライアント）でレンダリングされ、ブラウザがダウンロード後にHTML要素を生成し、すべてのJavaScriptコードを解析するモードです。

ユニバーサルレンダリング（Universal Rendering）は、ページのサーバーサイドとクライアントサイドのレンダリングを組み合わせたものです。ユニバーサルレンダリングでは、サーバーは完全にレンダリングされたHTMLページをブラウザに返し、JavaScript（Vue.js）コードがサーバー環境で実行され、HTMLドキュメントが生成されます。その後、クライアントはJavaScriptコードを読み込み、Vue.jsがドキュメントを制御し、インタラクティビティを可能にします。

Nuxt.jsには、ハイブリッド、CDNエッジワーカーでのレンダリング、ルートルールを使用した非常に細かい設定制御など、他のレンダリングモードもあります。これらのいくつかはまだ正式にリリースされていません。

## ミドルウェアの種類

Nuxt.jsには2つのミドルウェアの種類があります：Vue.jsアプリケーションのルートミドルウェアとNitroパートで実行されるノーマルミドルウェアです。

Nuxt 3では、ルートミドルウェアを匿名（またはインライン）、名前付きルート、グローバルの3つのタイプに分けています。

Nuxt.jsミドルウェアの最も一般的な使用例は、認証ガードです。しかし、Nuxt 3のサーバーミドルウェアの一部の使用例には、ルートパラメータの一致、リクエストクッキー取得、リクエストログの書き込み、APIのウォームアップなどがあります。

匿名（またはインライン）ルートミドルウェアは、ページ自体で直接定義します。

以下はミドルウェアを定義するページファイルの例です：

```html
<script setup>
definePageMeta({
  middleware: defineNuxtRouteMiddleware((to, from) => {
    console.log('to', to);
    console.log('from', from);
  }),
});
</script>
<template>
  …
</template>
```

名前付きルートミドルウェアは、*middleware/* ディレクトリに配置し、ページで使用すると非同期インポートによって自動的にロードされます。

*middleware/auth.ts* の例：

```javascript
export default defineNuxtRouteMiddleware(async (to, from) => {
  console.log('middleware/auth')
  console.log('to', to)
  console.log('from', from)
})
```

グローバルルートミドルウェアは、*middleware/* ディレクトリに配置し、*.global* の接尾辞を付けておくと、ルートの変更時に自動的に実行されます。

*middleware/auth.global.ts* の例：

```javascript
export default defineNuxtRouteMiddleware(async (to, from) => {
  console.log('middleware/auth.global')
})
```

ご覧の通り、構文には違いはありません。ただし、グローバルは直接呼び出されていなくても、任意のルートにアクセスする際に実行されるという微妙な違いがあります。

## 名前付きルートミドルウェア

上記の例で提案されているファイル構造を仮定すると、認証ガードのミドルウェアは *middleware/auth.ts* に配置されます。

ページファイルでは、次のようにルートミドルウェアを参照できます：

```html
<script setup>
  definePageMeta({
    middleware: ["auth"]
    // または middleware: 'auth'
  })
</script>
```

この方法の最も重要な利点の1つは、どのページがミドルウェアを必要とするかをより制御できることです。

## ミドルウェアの実行タイミングの制御

アプリケーションがSSRモードで実行されている場合、Nuxtはミドルウェアを初期ページのレンダリング時とクライアントサイドで再度実行します。プロセスオブジェクトを使用することで、コードの実行タイミングを制御できます。

以下はNuxt.js公式ドキュメントからのコード例で、ランタイムを制御するためのいくつかの可能性を示しています。

```javascript
export default defineNuxtRoute

Middleware(to => {
  // サーバー上でミドルウェアをスキップ
  if (process.server) return
  // クライアントサイドではミドルウェアを完全にスキップ
  if (process.client) return
  // または、初回のクライアントロード時のみミドルウェアをスキップ
  const nuxtApp = useNuxtApp()
  if (process.client && nuxtApp.isHydrating &&　nuxtApp.payload.serverRendered) return
})
```

## パラメータの概要

ルートミドルウェアは、ナビゲーションに直接関連しています。現在のルートと次のルートの間で動作し、引数でこの情報にアクセスできます。

Nuxt.jsミドルウェア関数は、contextとrouteの2つのパラメータを受け取ることができます。contextパラメータにはアプリ、ブラウザ、ルートに関する情報が、routeパラメータにはリクエストされたルートデータが格納されます。これらのパラメータで利用可能な情報を操作し、ミドルウェア関数の実行方法を制御するために使用することができます。

```javascript
export default defineNuxtRouteMiddleware((to, from) => {
  if (to.params.id === '1') {
    return abortNavigation()
  }
  return navigateTo('/')
})
```

Nuxt.jsは、ミドルウェアから直接2つのグローバルヘルパーを返すことができます：

- *navigateTo* は、指定されたルートにリダイレクトするために使用できます。これはプラグインやミドルウェア内でのプログラムによるユーザーの場所の変更に便利です。また、直接 *navigateTo* を呼び出してページナビゲーションを実行することもできます。

- *abortNavigation* は、オプションのエラーメッセージと、ともにナビゲーションを完全に停止することができます。アプリケーションの特定のページやセクションへの移動を防止する必要がある場合に役立ちます。

## 詳細はこちら

- [ミドルウェアディレクトリ](https://nuxt.com/docs/guide/directory-structure/middleware)
- [abortNavigationヘルパー](https://nuxt.com/docs/api/utils/abort-navigation)
- [navigateToヘルパー](https://nuxt.com/docs/api/utils/navigate-to)