middlewareとは?
middleware
とは、特定のルートに移動する前に何らかの処理を実行したい場合に使用するNuxtの機能です。
例えば、認証前のユーザーをリダイレクトさせたい場合などに使用します。
Nuxt3では2つの方法でmiddleware
を定義できます。
1. middlewareディレクトリを使用する
「middleware」ディレクトリ以下に、処理を実行するts
ファイルを置くことでミドルウェアを登録することができます。
ディレクトリとミドルウェアファイルの作成
% mkdir middleware && touch $_/auth.ts
middlewareの登録
ミドルウェアを登録するには、defineNuxtRouteMiddleware
を使用します。
引数には2つの値が取れます。
to
... ページ遷移先のルート情報from
... ページ遷移前のルート情報
middleware/auth.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
console.log('middleware/auth')
console.log('to', to)
console.log('from', from)
})
第三引数のnext
は取得できません。
vue-router docsのナビゲーションガードとは異なり、3番目の
next()
引数は渡されず、リダイレクトまたはルートキャンセルは、ミドルウェアから値を返すことによって処理されます。
middlewareの呼び出し
呼び出しにはページファイルのdefinePageMeta
を使用します。
Nuxt3ではレイアウトファイルからのミドルウェアの呼び出しはできません。
pages/index.vue
<script setup lang="ts">
definePageMeta({
middleware: ['auth']
})
</script>
/test
から/
に移動した際のログは以下の通りです。
console
middleware/auth
to {fullPath: '/', path: '/', query: {…}, hash: '', name: 'index', …}
from {fullPath: '/test', path: '/test', query: {…}, hash: '', name: 'test', …}
ページ遷移がサーバーを経由する場合、サーバ側でもミドルウェアが呼び出されます。
terminal
2. addRouteMiddlewareを使用する
ミドルウェアを動的に追加するaddRouteMiddleware
を使用すれば、「plugins」ディレクトリ内でも定義できます。
ディレクトリとプラグインファイルの作成
% mkdir plugins && touch $_/middleware.ts
プラグインファイルはNuxt2と同じく
nuxt.config.ts
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
plugins: [
'~/plugins/middleware'
]
})
pluginの登録
Nuxt3のプラグインにはdefineNuxtPlugin
を使用します。
渡される引数は、Nuxt3のインスタンスであるnuxtApp
のみです。
plugins/middleware.ts
export default defineNuxtPlugin((nuxtApp) => {
})
middlewareの登録
ミドルウェアを登録するには、addRouteMiddleware
を使用します。
-
addRouteMiddleware('key', function())
-
第一引数 ... 任意のキー(呼出名)。
-
第二引数 ... 実行したい処理。
-
plugins/middleware.ts
export default defineNuxtPlugin((nuxtApp) => {
addRouteMiddleware('local-middleware', () => {
console.log('plugins/middleware/local')
console.log('nuxtApp', nuxtApp)
})
})
middlewareの呼び出し
addRouteMiddleware
で登録したミドルウェアも呼び出し方法は同じです。
pages/index.vue
<script setup lang="ts">
definePageMeta({
middleware: ['local-middleware']
})
</script>
console
plugins/middleware/local
nuxtApp {globalName: 'nuxt', payload: Proxy, isHydrating: true, _asyncDataPromises: {…}, provide: ƒ, …}
addRouteMiddlewareのタイプエラー回避
addRouteMiddleware
を使用する方法は、型チェックを行うVolarがエラーを吐きます。
type MiddlewareKey
は「middleware」ディレクトリにファイルを作成すると自動で値が追加されます。
その実態は
.nuxt/types/middleware.d.ts
import type { NavigationGuard } from 'vue-router'
export type MiddlewareKey = "auth"
declare module "/<Project path>/node_modules/nuxt3/dist/pages/runtime/composables" {
interface PageMeta {
middleware?: MiddlewareKey | NavigationGuard | Array<MiddlewareKey | NavigationGuard>
}
}
addRouteMiddleware
で追加したmiddleware
はtype MiddlewareKey
に名前が追加されません。
回避策としてTypeScriptのas
を使用し、型を上書きします。
pages/index.vue
<script setup lang="ts">
/**
* MiddlewareKey type error 回避策
* addRouteMiddleware()で追加したmiddlewareキーを手動で追加する
* Nuxt version 3.0.0-27444434.856c01a
*/
import { MiddlewareKey } from '~/.nuxt/types/middleware'
type AddRouteMiddleware = MiddlewareKey & 'local-middleware'
definePageMeta({
middleware: ['local-middleware'] as Array<AddRouteMiddleware>
})
</script>
Nuxt3のグローバルミドルウェア
全てのルートで実行したい処理がある場合は、グローバルミドルウェアを使用します。
1. middlewareディレクトリを使用する
「middleware」ディレクトリ以下に作成する場合は、.global
がついたミドルウェアファイルを作成します。
グローバルミドルウェアの作成
% touch middleware/auth.global.ts
middleware/auth.global.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
console.log('middleware/auth.global')
})
.global
のファイルは呼び出し作業は不要です。
どのルートに遷移しても下記のコンソールが出力されます。
console
middleware/auth.global
2. addRouteMiddlewareを使用する
addRouteMiddleware
を使用してグローバルミドルウェアを登録する場合、{ global: true }
オプションを渡します。
plugins/middleware.ts
export default defineNuxtPlugin((nuxtApp) => {
addRouteMiddleware('global-middleware', () => {
console.log('plugins/middleware/global')
}, { global: true })
})
ただしこの方法、middleware
がなぜか2回呼ばれます。
Beta版のうちは使用しない方が良いかもしれません。
console
navigateToは無限ループになるバグあり
下記はNuxt Version:
3.0.0-27444434.856c01a
の状況です。
middleware
でリダイレクトを行うには、navigateTo('/')
またはnavigateTo({ path: '/' })
を使用します。
middleware/auth.global.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
console.log('middleware/auth.global')
// /testにリダイレクトするコード
return navigateTo('/test')
})
グローバルミドルウェアのnavigateTo
はVue Routerが無限ループを引き起こします。
Detected an infinite redirection in a navigation guard when going from "/" to "/test".
Aborting to avoid a Stack Overflow. This will break in production if not fixed.
terminal
これはaddRouteMiddleware
を使用しても結果は同じです。
現状のNuxt3では、グローバルミドルウェアでのリダイレクト処理は実行できません。
ローカルミドルウェアならnavigateToが使用可能
回避策として、ローカルミドルウェアにnavigateTo
を使用しリダイレクト処理を行います。
middleware/auth.ts
export default defineNuxtRouteMiddleware(async (to, from) => {
console.log('middleware/auth')
return navigateTo('/test')
})
ただし、グローバルに使用する場合は全てのページにミドルウェアを登録する必要があります。
pages/index.vue
<script setup lang="ts">
definePageMeta({
middleware: ['auth']
})
</script>
Nuxt3ではレイアウトファイルのmiddleware
が無くなったため八方塞がりの状況です。
今後の改善を待ちましょう。
Nuxt3beta middlewareまとめ
middleware
を登録する2つの方法- 「middleware」ディレクトリ内のファイルで処理を記述する
addRouteMiddleware
でミドルウェアを登録する
middleware
の呼出し- ページファイルの
definePageMeta.middleware
から呼び出す - レイアウトファイルからの呼出不可
- 【バグ?】
addRouteMiddleware
で登録したミドルウェアのキーが追加されない - 【バグ回避】
type MiddlewareKey
に手動でキーを追加する
- ページファイルの
- グローバルミドルウェア
- 「middleware」ディレクトリを使用する場合、ファイル名に
.global
を付ける addRouteMiddleware
を使用する場合、{ global: true }
オプションを追加する- 【バグ?】リダイレクトを行う
navigateTo
はエラーとなり使用不可 - 【バグ回避】リダイレクト処理はローカルミドルウェアを使用する
- 「middleware」ディレクトリを使用する場合、ファイル名に