after

Функция after позволяет запланировать выполнение задач после завершения ответа (или предварительного рендеринга). Это полезно для задач и других побочных эффектов, которые не должны блокировать ответ, таких как логирование и аналитика.

Её можно использовать в Серверных Компонентах (включая generateMetadata), Серверных Действиях, Обработчиках Маршрутов и Промежуточном ПО.

Функция принимает колбэк, который будет выполнен после завершения ответа (или предварительного рендеринга):

import { after } from 'next/server'
// Пользовательская функция логирования
import { log } from '@/app/utils'

export default function Layout({ children }: { children: React.ReactNode }) {
  after(() => {
    // Выполняется после рендеринга макета и отправки пользователю
    log()
  })
  return <>{children}</>
}
import { after } from 'next/server'
// Пользовательская функция логирования
import { log } from '@/app/utils'

export default function Layout({ children }) {
  after(() => {
    // Выполняется после рендеринга макета и отправки пользователю
    log()
  })
  return <>{children}</>
}

Важно знать: after не является Динамическим API, и её вызов не делает маршрут динамическим. Если она используется в статической странице, колбэк выполнится во время сборки или при ревалидации страницы.

Справочник

Параметры

  • Колбэк-функция, которая будет выполнена после завершения ответа (или предварительного рендеринга).

Длительность

after будет выполняться в течение стандартного или настроенного максимального времени выполнения маршрута для вашей платформы. Если платформа поддерживает это, вы можете настроить лимит времени с помощью конфигурации сегмента маршрута maxDuration.

Важно знать

  • after будет выполнена даже если ответ не завершился успешно, включая случаи возникновения ошибки или вызова notFound/redirect.
  • Вы можете использовать React cache для дедупликации функций, вызываемых внутри after.
  • after может быть вложена в другие вызовы after. Например, вы можете создавать утилитные функции, оборачивающие вызовы after для добавления дополнительной функциональности.

Примеры

С API запросов

Вы можете использовать API запросов, такие как cookies и headers, внутри after в Серверных Действиях и Обработчиках Маршрутов. Это полезно для логирования активности после мутации. Например:

import { after } from 'next/server'
import { cookies, headers } from 'next/headers'
import { logUserAction } from '@/app/utils'

export async function POST(request: Request) {
  // Выполнение мутации
  // ...

  // Логирование пользовательской активности для аналитики
  after(async () => {
    const userAgent = (await headers().get('user-agent')) || 'unknown'
    const sessionCookie =
      (await cookies().get('session-id'))?.value || 'anonymous'

    logUserAction({ sessionCookie, userAgent })
  })

  return new Response(JSON.stringify({ status: 'success' }), {
    status: 200,
    headers: { 'Content-Type': 'application/json' },
  })
}
import { after } from 'next/server'
import { cookies, headers } from 'next/headers'
import { logUserAction } from '@/app/utils'

export async function POST(request) {
  // Выполнение мутации
  // ...

  // Логирование пользовательской активности для аналитики
  after(async () => {
    const userAgent = (await headers().get('user-agent')) || 'unknown'
    const sessionCookie =
      (await cookies().get('session-id'))?.value || 'anonymous'

    logUserAction({ sessionCookie, userAgent })
  })

  return new Response(JSON.stringify({ status: 'success' }), {
    status: 200,
    headers: { 'Content-Type': 'application/json' },
  })
}

Однако вы не можете использовать эти API запросов внутри after в Серверных Компонентах. Это связано с тем, что Next.js должен знать, какая часть дерева обращается к API запросов для поддержки Частичного Предварительного Рендеринга, но after выполняется после жизненного цикла рендеринга React.

Поддержка платформ

Вариант развертыванияПоддержка
Сервер Node.jsДа
Docker контейнерДа
Статический экспортНет
АдаптерыЗависит от платформы

Узнайте, как настроить after при самостоятельном хостинге Next.js.

Справочник: поддержка after для serverless-платформ Использование after в serverless-контексте требует ожидания завершения асинхронных задач после отправки ответа. В Next.js и Vercel это достигается с помощью примитива waitUntil(promise), который продлевает время жизни serverless-вызова до завершения всех промисов, переданных в waitUntil.

Если вы хотите, чтобы ваши пользователи могли использовать after, вам необходимо предоставить свою реализацию waitUntil, которая работает аналогичным образом.

Когда вызывается after, Next.js обращается к waitUntil следующим образом:

const RequestContext = globalThis[Symbol.for('@next/request-context')]
const contextValue = RequestContext?.get()
const waitUntil = contextValue?.waitUntil

Это означает, что globalThis[Symbol.for('@next/request-context')] должен содержать объект следующего вида:

type NextRequestContext = {
  get(): NextRequestContextValue | undefined
}

type NextRequestContextValue = {
  waitUntil?: (promise: Promise<any>) => void
}

Вот пример реализации:

import { AsyncLocalStorage } from 'node:async_hooks'

const RequestContextStorage = new AsyncLocalStorage<NextRequestContextValue>()

// Определяем и внедряем аксессор, который будет использовать Next.js
const RequestContext: NextRequestContext = {
  get() {
    return RequestContextStorage.getStore()
  },
}
globalThis[Symbol.for('@next/request-context')] = RequestContext

const handler = (req, res) => {
  const contextValue = { waitUntil: YOUR_WAITUNTIL }
  // Предоставляем значение
  return RequestContextStorage.run(contextValue, () => nextJsHandler(req, res))
}

История версий

ВерсияОписание
v15.1.0after стала стабильной.
v15.0.0-rcВведена unstable_after.