middleware
Nuxt は、アプリケーション全体で使用できるカスタマイズ可能な**ルートミドルウェア**フレームワークを提供します。これは、特定のルートに移動する前に実行したいコードを抽出するのに最適です。
ルートミドルウェアには3種類あります。
- 匿名(またはインライン)ルートミドルウェアは、ページ内で直接定義されます。
- 名前付きルートミドルウェアは、
middleware/
に配置され、ページで使用されると非同期インポートによって自動的に読み込まれます。 - グローバルルートミドルウェアは、
.global
サフィックス付きでmiddleware/
に配置され、すべてのルート変更時に実行されます。
最初の2種類のルートミドルウェアは、definePageMeta
で定義できます。
myMiddleware
はmy-middleware
になります。使用方法
ルートミドルウェアは、現在のルートと次のルートを引数として受け取るナビゲーションガードです。
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つのグローバルに利用可能なヘルパーを提供します。
navigateTo
- 指定されたルートにリダイレクトします。abortNavigation
- ナビゲーションを中止します(オプションでエラーメッセージを指定できます)。
vue-router
のナビゲーションガードとは異なり、3番目のnext()
引数は渡されず、**リダイレクトまたはルートのキャンセルは、ミドルウェアから値を返すことで処理されます。**
可能な戻り値は次のとおりです。
- なし(単純な
return
または戻り値なし)- ナビゲーションをブロックせず、次のミドルウェア関数(存在する場合)に移動するか、ルートナビゲーションを完了します。 return navigateTo('/')
- 指定されたパスにリダイレクトし、サーバー側でリダイレクトが行われる場合はリダイレクトコードを302
Foundに設定します。return navigateTo('/', { redirectCode: 301 })
- 指定されたパスにリダイレクトし、サーバー側でリダイレクトが行われる場合はリダイレクトコードを301
Moved Permanentlyに設定します。return abortNavigation()
- 現在のナビゲーションを停止します。return abortNavigation(error)
- エラーを使用して現在のナビゲーションを拒否します。
ミドルウェアの順序
ミドルウェアは次の順序で実行されます。
- グローバルミドルウェア
- ページで定義されたミドルウェアの順序(配列構文で複数のミドルウェアが宣言されている場合)
たとえば、次のミドルウェアとコンポーネントがあるとします。
-| middleware/
---| analytics.global.ts
---| setup.global.ts
---| auth.ts
<script setup lang="ts">
definePageMeta({
middleware: [
function (to, from) {
// Custom inline middleware
},
'auth',
],
});
</script>
ミドルウェアは次の順序で実行されると予想されます。
analytics.global.ts
setup.global.ts
- カスタムインラインミドルウェア
auth.ts
グローバルミドルウェアの順序付け
デフォルトでは、グローバルミドルウェアはファイル名に基づいてアルファベット順に実行されます。
ただし、特定の順序を定義する必要がある場合があります。たとえば、最後のシナリオでは、setup.global.ts
をanalytics.global.ts
の前に実行する必要があります。その場合は、グローバルミドルウェアに「アルファベット順」の番号を接頭辞として付けることをお勧めします。
-| middleware/
---| 01.setup.global.ts
---| 02.analytics.global.ts
---| auth.ts
10.new.global.ts
は2.new.global.ts
の前にきます。これが、例で1桁の数字に0
を接頭辞として付ける理由です。ミドルウェアの実行タイミング
サイトがサーバーサイドレンダリングまたは生成されている場合、最初のページのミドルウェアは、ページがレンダリングされるときとクライアント側で再度実行されます。これは、ミドルウェアにブラウザ環境が必要な場合(生成されたサイトがある場合、応答を積極的にキャッシュする場合、またはローカルストレージから値を読み取る場合など)に必要になる可能性があります。
ただし、この動作を回避したい場合は、次のことができます。
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
フック内で名前付きルートミドルウェアを追加できます。
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)
}
}
})