middleware

Nuxt 提供中介軟體,用於在導航到特定路由之前執行程式碼。

Nuxt 提供了一個可定製的路由中介軟體框架,您可以在整個應用程式中使用它,非常適合提取需要在導航到特定路由之前執行的程式碼。

路由中介軟體有三種類型:

  1. 匿名(或內聯)路由中介軟體直接在頁面中定義。
  2. 命名路由中介軟體,放置在 app/middleware/ 目錄中,並在頁面中使用時透過非同步匯入自動載入。
  3. 全域性路由中介軟體,放置在 app/middleware/ 目錄中,帶有 .global 字尾,並在每次路由更改時執行。

前兩種路由中介軟體可以在 definePageMeta 中定義。

中介軟體名稱會規範化為 kebab-case:myMiddleware 會變成 my-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 提供了兩個可直接從中介軟體返回的全域性可用輔助函式。

  1. navigateTo - 重定向到給定路由
  2. abortNavigation - 中止導航,並可選擇附帶錯誤訊息。

來自 vue-router導航守衛不同,它不傳遞第三個 next() 引數,重定向或路由取消透過從中介軟體返回一個值來處理

可能的返回值包括:

  • 無(一個簡單的 return 或根本沒有返回值) - 不會阻止導航,並將移動到下一個中介軟體函式(如果有),或完成路由導航。
  • return navigateTo('/') - 重定向到給定路徑,如果重定向發生在伺服器端,則將重定向程式碼設定為302 Found
  • return navigateTo('/', { redirectCode: 301 }) - 重定向到給定路徑,並將重定向程式碼設定為301 Moved Permanently
  • return abortNavigation() - 停止當前導航。
  • return abortNavigation(error) - 拒絕當前導航並返回錯誤。
更多資訊請閱讀 文件 > 4 X > API > 工具 > 導航到
更多資訊請閱讀 文件 > 4 X > API > 工具 > 中止導航
我們建議使用上述輔助函式來執行重定向或停止導航。在vue-router 文件中描述的其他可能的返回值可能有效,但將來可能會有重大更改。

中介軟體順序

中介軟體按以下順序執行:

  1. 全域性中介軟體
  2. 頁面定義的中介軟體順序(如果使用陣列語法聲明瞭多箇中間件)

例如,假設您有以下中介軟體和元件:

app/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.ts 可能需要在 analytics.global.ts 之前執行。在這種情況下,我們建議為全域性中介軟體加上“字母”編號字首。

目錄結構
-| middleware/
---| 01.setup.global.ts
---| 02.analytics.global.ts
---| auth.ts
如果您不熟悉“字母”編號,請記住檔名按字串排序,而不是按數字值排序。例如,10.new.global.ts 會排在 2.new.global.ts 之前。這就是為什麼示例中將一位數字加字首 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 檢查是否正在處理錯誤。

在中介軟體中訪問路由

在中介軟體中始終使用 tofrom 引數來訪問下一個和上一個路由。避免在此上下文中完全使用 useRoute() 可組合函式。中介軟體中沒有“當前路由”的概念,因為中介軟體可以中止導航或重定向到不同的路由。useRoute() 可組合函式在此上下文中將始終不準確。

有時,您可能會呼叫內部使用 useRoute() 的可組合函式,即使您的中介軟體中沒有直接呼叫,這也會觸發此警告。這會導致與上面相同的問題,因此在使用中介軟體時,您應該將函式結構化為接受路由作為引數。
export default defineNuxtRouteMiddleware((to) => {
  // passing the route to the function to avoid calling `useRoute()` in middleware
  doSomethingWithRoute(to)

  // ❌ this will output a warning and is NOT recommended
  callsRouteInternally()
})

動態新增中介軟體

可以使用 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 路由中介軟體將執行。

文件 > 4 X > 示例 > 路由 > 中介軟體中閱讀和編輯即時示例。

在構建時設定中介軟體

除了在每個頁面上使用 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 */ Math.random() > 0.5) {
            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)
    },
  },
})