Nuxt 3 / 4 的 Route Middleware:進頁面前先做判斷
整理 Nuxt 3 與 Nuxt 4 的 Route Middleware,用 defineNuxtRouteMiddleware 在進入頁面前檢查登入狀態,搭配 navigateTo 重新導向,並說明一般 middleware、global middleware 與 definePageMeta 的用法。
W
Nuxt 2 時期就有 Middleware,常拿來在進頁面前做登入驗證。
Middleware 可以先簡單理解成:
使用者準備進入某個頁面之前,先執行一段檢查。
最常見的用途就是登入驗證。
例如:
使用者進入 /member
↓
先檢查有沒有登入
↓
有登入 → 繼續進入
沒登入 → 導到 /login
Nuxt 3 開始使用 defineNuxtRouteMiddleware(),Nuxt 4 也延續相同方式。
建立登入驗證 Middleware
Nuxt 4 建立:
app/middleware/auth.ts
Nuxt 3 則是:
middleware/auth.ts
內容:
export default defineNuxtRouteMiddleware(() => {
const authState = useAuthState()
if (!authState.value) {
return navigateTo('/login')
}
})
可以白話理解成:
如果沒有登入
→ 不要繼續進原本的頁面
→ 改去 /login
navigateTo() 就是 Nuxt 3 / 4 用來做頁面導向的方式。
在頁面指定 Middleware
不是每一頁都需要登入驗證。
例如只有會員頁需要,可以在頁面裡使用:
<script setup lang="ts">
definePageMeta({
middleware: 'auth'
})
</script>
這樣進入這個頁面之前,就會先執行:
app/middleware/auth.ts
Nuxt 3 則是:
middleware/auth.ts
搭配頁面的自訂設定
也可以自己在 definePageMeta() 加上設定:
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
requiresAuth: true
})
</script>
Middleware 裡就能讀:
export default defineNuxtRouteMiddleware((to) => {
if (to.meta.requiresAuth) {
const authState = useAuthState()
if (!authState.value) {
return navigateTo('/login')
}
}
})
這裡的:
to
代表「準備前往的頁面」。
所以:
to.meta.requiresAuth
就是查看那個頁面有沒有設定:
requiresAuth: true
全站都要執行:.global
如果不想每個頁面都寫:
middleware: 'auth'
可以把檔名改成:
auth.global.ts
Nuxt 4:
app/middleware/auth.global.ts
Nuxt 3:
middleware/auth.global.ts
.global 代表:
每次切換頁面都執行這支 middleware。
例如:
middleware/
├── auth.ts
└── analytics.global.ts
可以理解成:
auth.ts
→ 頁面有指定才執行
analytics.global.ts
→ 每個頁面都執行
如果整個後台都需要登入驗證,也可以考慮使用 global middleware。
注意不要一直重新導向
假設寫成:
export default defineNuxtRouteMiddleware(() => {
return navigateTo('/login')
})
如果連 /login 本身也會執行這支 middleware,就可能一直重新導向。
因此通常要先判斷:
export default defineNuxtRouteMiddleware((to) => {
const authState = useAuthState()
if (
!authState.value &&
to.path !== '/login'
) {
return navigateTo('/login')
}
})
意思就是:
沒有登入
而且現在不是登入頁
→ 才導向 /login
Route Middleware 和 Server Middleware 不一樣
Nuxt 裡其實有兩種名字很像的 middleware。
Route Middleware
Nuxt 4:
app/middleware/
用途範例:
進入頁面前檢查
登入驗證
權限判斷
頁面重新導向
Server Middleware
server/middleware/
用途比較像:
處理 HTTP request
記錄 log
設定 request context
Server 端驗證
兩個不是同一套東西。
如果是:
使用者能不能進這個 Vue 頁面?
通常是在講 Route Middleware。
Nuxt 2、3、4 對照
| Nuxt 2 | Nuxt 3 | Nuxt 4 | |
|---|---|---|---|
| Route Middleware 位置 | middleware/ | middleware/ | app/middleware/ |
| Middleware 寫法 | context function | defineNuxtRouteMiddleware() | defineNuxtRouteMiddleware() |
| 重新導向 | redirect() | navigateTo() | navigateTo() |
| 頁面設定 | Options API | definePageMeta() | definePageMeta() |
| 全域 Middleware | 另外設定 | .global.ts | .global.ts |
| 讀取頁面 meta | 舊 route meta | to.meta | to.meta |
所以從 Nuxt 3 升到 Nuxt 4:
Middleware 的概念和寫法幾乎沒有變。
主要只是檔案從:
middleware/
搬到:
app/middleware/
小結
可以把 Route Middleware 記成:
進頁面之前,先幫我檢查一下。
例如登入驗證:
export default defineNuxtRouteMiddleware(() => {
const authState = useAuthState()
if (!authState.value) {
return navigateTo('/login')
}
})
頁面需要使用時:
definePageMeta({
middleware: 'auth'
})
如果每一頁都要執行,就把檔名改成:
auth.global.ts
Nuxt 3 與 Nuxt 4 的寫法基本相同,最大的差別只是 Nuxt 4 的 Route Middleware 放在:
app/middleware/