透過 100 多個技巧的集合來學習 Nuxt!

錯誤處理

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

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

  • Vue 渲染生命週期期間的錯誤 (SSR & CSR)
  • 伺服器和客戶端啟動錯誤 (SSR + CSR)
  • Nitro 伺服器生命週期中的錯誤(server/ 目錄)
  • 下載 JS 區塊時發生錯誤
SSR 代表 伺服器端渲染 (Server-Side Rendering),而 CSR 代表 用戶端渲染 (Client-Side Rendering)

Vue 錯誤

您可以使用 onErrorCaptured 來掛鉤 Vue 錯誤。

此外,Nuxt 提供了一個 vue:error Hook,當任何錯誤傳播到最上層時,將會被呼叫。

如果您正在使用錯誤回報框架,您可以通过 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 Hook 是基於 onErrorCaptured 生命周期 Hook。

啟動錯誤

如果 Nuxt 應用程式啟動時發生任何錯誤,Nuxt 將會呼叫 app:error Hook。

這包括

  • 執行 Nuxt 插件
  • 處理 app:createdapp:beforeMount Hook
  • 將您的 Vue 應用程式渲染成 HTML(在 SSR 期間)
  • 掛載應用程式(在用戶端),雖然您應該使用 onErrorCapturedvue:error 處理此情況
  • 處理 app:mounted Hook

Nitro 伺服器錯誤

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

JS 區塊錯誤

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

您可以將 experimental.emitRouteChunkError 設定為 false(完全停用掛鉤這些錯誤)或 manual(如果您想要自行處理)來變更此行為。如果您想要手動處理區塊載入錯誤,您可以查看 自動實作 以取得想法。

錯誤頁面

當 Nuxt 遇到嚴重錯誤(伺服器上任何未處理的錯誤,或在用戶端以 fatal: true 建立的錯誤)時,它將會渲染 JSON 回應(如果使用 Accept: application/json 標頭請求)或觸發全螢幕錯誤頁面。

當在伺服器生命週期中發生錯誤時,可能是因為

  • 處理您的 Nuxt 插件
  • 將您的 Vue 應用程式渲染成 HTML
  • 伺服器 API 路由拋出錯誤

它也可能在用戶端發生,當

  • 處理您的 Nuxt 插件
  • 在掛載應用程式之前(app:beforeMount Hook)
  • 如果錯誤沒有使用 onErrorCapturedvue:error Hook 處理,則在掛載您的應用程式時
  • Vue 應用程式在瀏覽器中初始化和掛載時(app:mounted)。
探索所有 Nuxt 生命週期 Hook。

您可以透過在應用程式的原始碼目錄中新增 ~/error.vue(與 app.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 composable(可以在頁面/元件 setup 函式中呼叫)或 vue:error runtime nuxt hook(可以在 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 composable 的資訊。

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,它將會觸發重新渲染預設插槽;您需要確保錯誤已完全解決,否則錯誤插槽只會被渲染第二次。)

如果您導覽到另一個路由,錯誤將會自動清除。
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>
文件 > 範例 > 進階 > 錯誤處理 中閱讀並編輯即時範例。