Nuxt Nation カンファレンスが開催されます。11月12日~13日、ご参加ください。

middleware

Nuxt は、特定のルートに移動する前にコードを実行するためのミドルウェアを提供します。

Nuxt は、アプリケーション全体で使用できるカスタマイズ可能な**ルートミドルウェア**フレームワークを提供します。これは、特定のルートに移動する前に実行したいコードを抽出するのに最適です。

ルートミドルウェアには3種類あります。

  1. 匿名(またはインライン)ルートミドルウェアは、ページ内で直接定義されます。
  2. 名前付きルートミドルウェアは、middleware/に配置され、ページで使用されると非同期インポートによって自動的に読み込まれます。
  3. グローバルルートミドルウェアは、.globalサフィックス付きでmiddleware/に配置され、すべてのルート変更時に実行されます。

最初の2種類のルートミドルウェアは、definePageMetaで定義できます。

ミドルウェアの名前はケバブケースに変換されます。myMiddlewaremy-middlewareになります。
ルートミドルウェアは、NuxtアプリのVue部分内で実行されます。名前が似ていますが、アプリのNitroサーバー部分で実行されるサーバーミドルウェアとは全く異なります。

使用方法

ルートミドルウェアは、現在のルートと次のルートを引数として受け取るナビゲーションガードです。

middleware/my-middleware.ts
export default 
defineNuxtRouteMiddleware
((
to
,
from
) => {
if (
to
.
params
.
id
=== '1') {
return
abortNavigation
()
} // In a real app you would probably not redirect every route to `/` // however it is important to check `to.path` before redirecting or you // might get an infinite redirect loop if (
to
.
path
!== '/') {
return
navigateTo
('/')
} })

Nuxt は、ミドルウェアから直接返すことができる2つのグローバルに利用可能なヘルパーを提供します。

  1. navigateTo - 指定されたルートにリダイレクトします。
  2. abortNavigation - ナビゲーションを中止します(オプションでエラーメッセージを指定できます)。

vue-routerナビゲーションガードとは異なり、3番目のnext()引数は渡されず、**リダイレクトまたはルートのキャンセルは、ミドルウェアから値を返すことで処理されます。**

可能な戻り値は次のとおりです。

  • なし(単純なreturnまたは戻り値なし)- ナビゲーションをブロックせず、次のミドルウェア関数(存在する場合)に移動するか、ルートナビゲーションを完了します。
  • return navigateTo('/') - 指定されたパスにリダイレクトし、サーバー側でリダイレクトが行われる場合はリダイレクトコードを302 Foundに設定します。
  • return navigateTo('/', { redirectCode: 301 }) - 指定されたパスにリダイレクトし、サーバー側でリダイレクトが行われる場合はリダイレクトコードを301 Moved Permanentlyに設定します。
  • return abortNavigation() - 現在のナビゲーションを停止します。
  • return abortNavigation(error) - エラーを使用して現在のナビゲーションを拒否します。
ドキュメント > API > ユーティリティ > navigateToで詳細をご覧ください。
ドキュメント > API > ユーティリティ > abortNavigationで詳細をご覧ください。
リダイレクトの実行やナビゲーションの停止には、上記のヘルパー関数の使用をお勧めします。vue-router のドキュメントに記載されている他の可能な戻り値は機能する可能性がありますが、将来変更される可能性があります。

ミドルウェアの順序

ミドルウェアは次の順序で実行されます。

  1. グローバルミドルウェア
  2. ページで定義されたミドルウェアの順序(配列構文で複数のミドルウェアが宣言されている場合)

たとえば、次のミドルウェアとコンポーネントがあるとします。

middleware/ ディレクトリ
-| middleware/
---| analytics.global.ts
---| setup.global.ts
---| auth.ts
pages/profile.vue
<script setup lang="ts">
definePageMeta({
  middleware: [
    function (to, from) {
      // Custom inline middleware
    },
    'auth',
  ],
});
</script>

ミドルウェアは次の順序で実行されると予想されます。

  1. analytics.global.ts
  2. setup.global.ts
  3. カスタムインラインミドルウェア
  4. auth.ts

グローバルミドルウェアの順序付け

デフォルトでは、グローバルミドルウェアはファイル名に基づいてアルファベット順に実行されます。

ただし、特定の順序を定義する必要がある場合があります。たとえば、最後のシナリオでは、setup.global.tsanalytics.global.tsの前に実行する必要があります。その場合は、グローバルミドルウェアに「アルファベット順」の番号を接頭辞として付けることをお勧めします。

ディレクトリ構造
-| middleware/
---| 01.setup.global.ts
---| 02.analytics.global.ts
---| auth.ts
「アルファベット順」の番号付けが初めての場合は、ファイル名は数値ではなく文字列としてソートされることに注意してください。たとえば、10.new.global.ts2.new.global.tsの前にきます。これが、例で1桁の数字に0を接頭辞として付ける理由です。

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

サイトがサーバーサイドレンダリングまたは生成されている場合、最初のページのミドルウェアは、ページがレンダリングされるときとクライアント側で再度実行されます。これは、ミドルウェアにブラウザ環境が必要な場合(生成されたサイトがある場合、応答を積極的にキャッシュする場合、またはローカルストレージから値を読み取る場合など)に必要になる可能性があります。

ただし、この動作を回避したい場合は、次のことができます。

middleware/example.ts
export default 
defineNuxtRouteMiddleware
(
to
=> {
// skip middleware on server if (import.meta.
server
) return
// skip middleware on client side entirely if (import.meta.
client
) return
// or only skip middleware on initial client load const
nuxtApp
=
useNuxtApp
()
if (import.meta.
client
&&
nuxtApp
.
isHydrating
&&
nuxtApp
.
payload
.
serverRendered
) return
})
エラーページのレンダリングは完全に別のページの読み込みであるため、登録されているミドルウェアはすべて再度実行されます。useErrorをミドルウェアで使用して、エラーが処理されているかどうかを確認できます。

ミドルウェアの動的な追加

グローバルまたは名前付きルートミドルウェアは、addRouteMiddleware() ヘルパー関数を使用して、プラグイン内などから手動で追加できます。

export default 
defineNuxtPlugin
(() => {
addRouteMiddleware
('global-test', () => {
console
.
log
('this global middleware was added in a plugin and will be run on every route change')
}, {
global
: true })
addRouteMiddleware
('named-test', () => {
console
.
log
('this named middleware was added in a plugin and would override any existing middleware of the same name')
}) })

ディレクトリ構造
-| middleware/
---| auth.ts

ページファイルでは、このルートミドルウェアを参照できます。

<script setup lang="ts">
definePageMeta({
  middleware: ["auth"]
  // or middleware: 'auth'
})
</script>

これで、そのページへのナビゲーションが完了する前に、auth ルートミドルウェアが実行されます。

ドキュメント > 例 > ルーティング > ミドルウェアでライブ例を参照および編集できます。

ビルド時のミドルウェアの設定

definePageMeta を各ページで使用せずに、pages:extend フック内で名前付きルートミドルウェアを追加できます。

nuxt.config.ts
import type { 
NuxtPage
} from 'nuxt/schema'
export default
defineNuxtConfig
({
hooks
: {
'pages:extend' (
pages
) {
function
setMiddleware
(
pages
:
NuxtPage
[]) {
for (const
page
of
pages
) {
if (/* some condition */ true) {
page
.
meta
||= {}
// Note that this will override any middleware set in `definePageMeta` in the page
page
.
meta
.middleware = ['named']
} if (
page
.
children
) {
setMiddleware
(
page
.
children
)
} } }
setMiddleware
(
pages
)
} } })