錯誤處理

瞭解如何在 Nuxt 中捕獲和處理錯誤。

Nuxt 是一個全棧框架,這意味著在不同上下文中可能會發生多種無法預防的使用者執行時錯誤。

  • Vue 渲染生命週期中的錯誤 (SSR & CSR)
  • 伺服器和客戶端啟動錯誤 (SSR + CSR)
  • Nitro 伺服器生命週期中的錯誤 (server/ 目錄)
  • 下載 JS 塊時出錯
SSR 代表伺服器端渲染CSR 代表客戶端渲染

Vue 錯誤

您可以使用以下方式掛鉤 Vue 錯誤onErrorCaptured.

此外,Nuxt 還提供了一個 vue:error 鉤子,如果任何錯誤傳播到頂層,該鉤子將被呼叫。

如果您使用錯誤報告框架,您可以透過以下方式提供全域性處理程式vueApp.config.errorHandler。它將接收所有 Vue 錯誤,即使它們已被處理。

plugins/error-handler.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
    // handle error, e.g. report to a service
  }

  // Also possible
  nuxtApp.hook('vue:error', (error, instance, info) => {
    // handle error, e.g. report to a service
  })
})
請注意,vue:error 鉤子基於onErrorCaptured生命週期鉤子。

啟動錯誤

如果啟動 Nuxt 應用程式時出現任何錯誤,Nuxt 將呼叫 app:error 鉤子。

這包括

  • 執行 Nuxt 外掛
  • 處理 app:createdapp:beforeMount 鉤子
  • 將 Vue 應用程式渲染為 HTML (在 SSR 期間)
  • 掛載應用程式 (在客戶端),儘管您應該使用 onErrorCapturedvue:error 處理這種情況
  • 處理 app:mounted 鉤子

Nitro 伺服器錯誤

您目前無法為這些錯誤定義伺服器端處理程式,但可以渲染錯誤頁面,請參閱渲染錯誤頁面部分。

JS 塊錯誤

您可能會由於網路連線失敗或新部署(導致舊的雜湊 JS 塊 URL 失效)而遇到塊載入錯誤。Nuxt 提供內建支援來處理塊載入錯誤,方法是在路由導航期間塊載入失敗時執行硬重新載入。

您可以透過將 experimental.emitRouteChunkError 設定為 false(完全停用這些錯誤的掛鉤)或設定為 manual 來更改此行為,如果您想自行處理它們。如果您想手動處理塊載入錯誤,您可以檢視自動實現以獲取想法。

錯誤頁面

當 Nuxt 遇到致命錯誤(伺服器上任何未處理的錯誤,或客戶端上使用 fatal: true 建立的錯誤)時,它將渲染 JSON 響應(如果請求帶有 Accept: application/json 標頭)或觸發全屏錯誤頁面。

在伺服器生命週期中,錯誤可能發生在

  • 處理您的 Nuxt 外掛
  • 將您的 Vue 應用程式渲染為 HTML
  • 伺服器 API 路由丟擲錯誤

它也可能發生在客戶端上,當

  • 處理您的 Nuxt 外掛
  • 掛載應用程式之前 (app:beforeMount 鉤子)
  • 如果錯誤沒有透過 onErrorCapturedvue:error 鉤子處理,則掛載您的應用程式
  • Vue 應用程式在瀏覽器中初始化並掛載 (app:mounted)。
發現所有 Nuxt 生命週期鉤子。

透過在應用程式的源目錄中,與 app.vue 一起新增 ~/error.vue 來定製預設錯誤頁面。

error.vue
<script setup lang="ts">
import type { NuxtError } from '#app'

const props = defineProps({
  error: Object as () => NuxtError,
})

const handleError = () => clearError({ redirect: '/' })
</script>

<template>
  <div>
    <h2>{{ error?.statusCode }}</h2>
    <button @click="handleError">
      Clear errors
    </button>
  </div>
</template>
閱讀更多關於 error.vue 及其用途。

對於自定義錯誤,我們強烈建議使用可在頁面/元件設定函式中呼叫的 onErrorCaptured 可組合函式,或可在 Nuxt 外掛中配置的 vue:error 執行時 Nuxt 鉤子。

plugins/error-handler.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('vue:error', (err) => {
    //
  })
})

當您準備好移除錯誤頁面時,您可以呼叫 clearError 輔助函式,該函式接受一個可選的重定向路徑(例如,如果您想導航到“安全”頁面)。

在使用任何依賴於 Nuxt 外掛的內容(例如 $routeuseRouter)之前,請務必檢查,因為如果外掛丟擲錯誤,則在您清除錯誤之前它不會重新執行。
渲染錯誤頁面是一個完全獨立的頁面載入,這意味著任何已註冊的中介軟體將再次執行。您可以使用 useError 在中介軟體中檢查錯誤是否正在處理。
如果您在 Node 16 上執行並在渲染錯誤頁面時設定了任何 cookie,它們將覆蓋先前設定的 cookie。我們建議使用較新版本的 Node,因為 Node 16 已於 2023 年 9 月達到生命週期結束。

錯誤工具

useError

TS 簽名
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>

此函式將返回正在處理的全域性 Nuxt 錯誤。

閱讀更多關於 useError 可組合函式。

createError

TS 簽名
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error

建立帶有附加元資料的錯誤物件。您可以傳遞一個字串作為錯誤 message,或一個包含錯誤屬性的物件。它可在應用程式的 Vue 和伺服器部分使用,旨在被丟擲。

如果您丟擲使用 createError 建立的錯誤

  • 在伺服器端,它將觸發一個全屏錯誤頁面,您可以使用 clearError 清除它。
  • 在客戶端,它將丟擲一個非致命錯誤供您處理。如果您需要觸發全屏錯誤頁面,可以透過設定 fatal: true 來實現。
pages/movies/[slug].vue
<script setup lang="ts">
const route = useRoute()
const { data } = await useFetch(`/api/movies/${route.params.slug}`)

if (!data.value) {
  throw createError({
    statusCode: 404,
    statusMessage: 'Page Not Found',
  })
}
</script>
閱讀更多關於 createError 工具。

showError

TS 簽名
function showError (err: string | Error | { statusCode, statusMessage }): Error

您可以在客戶端的任何時候,或者(在伺服器端)直接在中介軟體、外掛或 setup() 函式中呼叫此函式。它將觸發一個全屏錯誤頁面,您可以使用 clearError 清除它。

建議改用 throw createError()

閱讀更多關於 showError 工具。

clearError

TS 簽名
function clearError (options?: { redirect?: string }): Promise<void>

此函式將清除當前處理的 Nuxt 錯誤。它還接受一個可選的重定向路徑(例如,如果您想導航到“安全”頁面)。

閱讀更多關於 clearError 工具。

在元件中渲染錯誤

Nuxt 還提供了一個 <NuxtErrorBoundary> 元件,允許您在應用程式中處理客戶端錯誤,而無需用錯誤頁面替換整個網站。

此元件負責處理其預設插槽中發生的錯誤。在客戶端,它將阻止錯誤冒泡到頂層,並渲染 #error 插槽。

#error 插槽將接收 error 作為 prop。(如果您設定 error = null,它將觸發預設插槽的重新渲染;您需要確保錯誤已完全解決,否則錯誤插槽將再次渲染。)

如果您導航到另一個路由,錯誤將自動清除。
app/pages/index.vue
<template>
  <!-- some content -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <!-- You use the default slot to render your content -->
    <template #error="{ error, clearError }">
      You can display the error locally here: {{ error }}
      <button @click="clearError">
        This will clear the error.
      </button>
    </template>
  </NuxtErrorBoundary>
</template>
文件 > 4 X > 示例 > 高階 > 錯誤處理 中閱讀和編輯即時示例。