Nuxt Nation conference is coming. Join us on November 12-13.

Обработка ошибок

Узнайте как отлавливать и обрабатывать ошибки в Nuxt.

Nuxt является full-stack фреймворком, что означает, что существует несколько источников непредотвратимых пользовательских ошибок рантайма, которые могут произойти в разных контекстах:

  • Ошибки во время жизненного цикла рендеринга Vue (SSR & CSR)
  • Ошибки запуска сервера и клиента (SSR + CSR)
  • Ошибки во время жизненного цикла сервера Nitro (папка server/)
  • Ошибки загрузки JS чанков
SSR означает Server-Side Rendering (рендеринг на стороне сервера), а CSR - Client-Side Rendering (рендеринг на стороне клиента).

Ошибки 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
) => {
// обработка ошибки, например сообщить в сервис } // Также возможно
nuxtApp
.
hook
('vue:error', (
error
,
instance
,
info
) => {
// обработка ошибки, например сообщить в сервис }) })
Обратите внимание, что хук vue:error основан на хуке жизненного цикла onErrorCaptured.

Ошибки запуска

Nuxt вызовет хук app:error, если возникут любые ошибки на старте вашего приложения Nuxt.

Это включает:

  • запуск плагинов Nuxt
  • обработку хуков app:created и app:beforeMount
  • рендеринг приложения Vue в HTML (во время SSR)
  • монтирование приложения (на стороне клиента), хотя вы должны обрабатывать этот случай с помощью onErrorCaptured или vue:error
  • обработку хука app:mounted

Ошибки сервера Nitro

В настоящее время вы не можете определить обработчик ошибок на стороне сервера для этих ошибок, но вы можете отобразить страницу ошибки. См. раздел Отобразить страницу ошибки.

Ошибки с чанками JS

Вы можете столкнуться с ошибками загрузки чанков из-за сбоя в сетевом соединении или нового развертывания (которое делает недействительными ваши старые URL-адреса хешированных чанков JS). Nuxt предоставляет встроенную поддержку обработки ошибок загрузки чанков путем выполнения жесткой перезагрузки, когда чанк не удается загрузить во время навигации по маршруту.

Вы можете изменить это поведение, установив experimental.emitRouteChunkError в значение false (чтобы отключить обработку этих ошибок вообще) или в значение manual, если вы хотите обрабатывать их самостоятельно. Если вы хотите обрабатывать ошибки загрузки фрагментов вручную, вы можете ознакомиться с автоматической реализацией для получения идей.

Страница ошибки

Когда Nuxt сталкивается с фатальной ошибкой (любая необработанная ошибка на сервере или ошибка, созданная с помощью fatal: true, на клиенте), он либо рендерит JSON ответ (если был запрошен с хэдером Accept: application/json) или вызовет полноэкранную страницу ошибки.

Ошибка может возникуть во время жизненного цикла сервера, когда:

  • обрабатываются ваши плагины Nuxt
  • ваше Vue-приложение рендерится в HTML
  • маршрут API сервера кидает ошибку

Она также может возникнуть на стороне клиента, когда:

  • обрабатываются ваши плагины Nuxt
  • перед монтированием приложения (хук app:beforeMount)
  • монтируется ваше прилложение, если ошибка не была обработана с помощью onErrorCaptured или хука vue:error
  • Vue приложение было инициализировано и смонтировано в браузере (app:mounted).
Узнайте все хуки жизненного цикла Nuxt.

Настройте страницу ошибки по умолчанию, добавив ~/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">Очистить ошибки</button>
  </div>
</template>
Прочтите больше про error.vue и его использовании.

Для пользовательских ошибок мы настоятельно рекомендуем использовать композабл onErrorCaptured, который может быть вызван в setup-функции страницы/компонента или в рантайм-хуке Nuxt vue:error, который может быть настроен в Nuxt-плагине.

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

Когда вы будете готовы скрыть страницу ошибки, вы можете вызвать вспомогательную функцию clearError, которая принимает опциональный путь для редиректа (например, если вы хотите направить на 'безопасную' страницу).

Обязательно проверьте, прежде чем использовать что-либо, зависящее от плагинов Nuxt, например $route или useRouter, так как если плагин выдает ошибку, он не перезапустится, пока вы не устраните ошибку.
Рендеринг страницы ошибки - полностью отдельная загрузка страницы, что означает, что любой зарегистрированный middleware будет запущен снова. Вы можете использовать useError в middleware, чтобы проверить, обрабатывается ли ошибка.
Если вы используете Node 16 и устанавливаете файлы cookie, когда рендерите вашу страницу ошибки, они перезапишут ранее установленные cookie. Мы рекомендуем использовать более новую версию Node, так как Node 16 достиг конца жизни в сентябре 2023.

Утилиты для ошибок

useError

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

Эта функция вернет глобальную ошибку Nuxt, которая обрабатывается.

Прочитайте больше про композабл useError.

createError

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

Создаёт объект ошибки с дополнительными мета-данными. Вы можете передать строку, которая будет установлена в качестве сообщения об ошибке, или объект, содержащий свойства ошибки. Он может использоваться как в частях 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 Signature
function showError (err: string | Error | { statusCode, statusMessage }): Error

Вы можете вызвать эту функцию в любой момент на клиенте или (на сервере) непосредственно в middleware, плагине или функциях setup(). Это вызовет полноэкранную страницу ошибки, которую вы можете очистить с помощью clearError.

Вместо этого рекомендуется использовать throw createError().

Прочитайте больше про утилиту showError.

clearError

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

Эта функция очистит текущую обработанную ошибку Nuxt. Она также принимает опциональный путь для редиректа (например, если вы хотите направить на 'безопасную' страницу).

Прочитайте больше про утилиту clearError.

Отображение ошибки в компоненте

Nuxt также предоставляет компонент <NuxtErrorBoundary>, который позволяет вам обрабатывать ошибки на стороне клиента в вашем приложении, не заменяя весь сайт страницей ошибки.

Этот компонент отвечает за обработку ошибок, возникающих в его слоте по умолчанию. На стороне клиента это предотвратит появление ошибки на верхнем уровне и вместо этого отобразит слот #error.

Слот #error получит error как входной параметр. (Если вы установите error = null это вызовет ре-рендеринг слота по умолчанию; вам будет необходимо сперва убедиться, что ошибка полностью разрешена, иначе слот error отобразится во второй раз.)

Если вы перейдете на другой маршрут, ошибка будет очищена автоматически.
pages/index.vue
<template>
  <!-- какой-то контент -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <!-- Вы используете слот по умолчанию для отображения контента -->
    <template #error="{ error, clearError }">
      Вы можете отобразить ошибку здесь: {{ error }}
      <button @click="clearError">
        Это очистит ошибку.
      </button>
    </template>
  </NuxtErrorBoundary>
</template>
Прочитайте и отредактируйте живой пример в Docs > Examples > Advanced > Error Handling.