after

تسمح لك after بجدولة أعمال لتُنفذ بعد انتهاء الاستجابة (أو التصيير المسبق). هذا مفيد للمهام والآثار الجانبية التي لا يجب أن تعيق الاستجابة، مثل التسجيل والتحليلات.

يمكن استخدامها في مكونات الخادم (Server Components) (بما في ذلك generateMetadataإجراءات الخادم (Server Actions)، معالجات المسارات (Route Handlers)، والوسيط (Middleware).

تقبل الوظيفة رد اتصال (callback) سيتم تنفيذه بعد انتهاء الاستجابة (أو التصيير المسبق):

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 ليست واجهة برمجة ديناميكية (Dynamic API) واستدعاؤها لا يجعل المسار ديناميكيًا. إذا استُخدمت في صفحة ثابتة، سيتم تنفيذ رد الاتصال وقت البناء، أو عند إعادة التحقق من الصفحة.

المرجع

المعاملات

  • وظيفة رد اتصال (callback) سيتم تنفيذها بعد انتهاء الاستجابة (أو التصيير المسبق).

المدة

سيتم تشغيل after لمدة النظام الأساسي الافتراضية أو المدة القصوى المكونة لمسارك. إذا كان نظامك الأساسي يدعم ذلك، يمكنك تكوين حد المهلة باستخدام تكوين قطاع المسار maxDuration.

معلومات مفيدة

  • سيتم تنفيذ after حتى لو لم تكتمل الاستجابة بنجاح. بما في ذلك عند حدوث خطأ أو عند استدعاء notFound أو redirect.
  • يمكنك استخدام cache من React لإزالة التكرار من الوظائف المستدعاة داخل after.
  • يمكن تداخل after داخل استدعاءات after أخرى، على سبيل المثال، يمكنك إنشاء وظائف مساعدة تغلف استدعاءات after لإضافة وظائف إضافية.

أمثلة

مع واجهات برمجة الطلبات

يمكنك استخدام واجهات برمجة الطلبات مثل cookies وheaders داخل after في إجراءات الخادم (Server Actions) ومعالجات المسارات (Route Handlers). هذا مفيد لتسجيل النشاط بعد التحوير. على سبيل المثال:

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' },
  })
}

ومع ذلك، لا يمكنك استخدام واجهات برمجة الطلبات هذه داخل after في مكونات الخادم (Server Components). وذلك لأن Next.js يحتاج لمعرفة أي جزء من الشجرة يصل إلى واجهات برمجة الطلبات لدعم التصيير المسبق الجزئي (Partial Prerendering)، لكن after تعمل بعد دورة حياة تصيير React.

دعم المنصات

خيار النشرمدعوم
خادم Node.jsنعم
حاوية Dockerنعم
تصدير ثابتلا
المحولات (Adapters)حسب المنصة

تعرف على كيفية تكوين after عند استضافة Next.js ذاتيًا.

مرجع: دعم after لمنصات بلا خادم يتطلب استخدام after في سياق بلا خادم انتظار انتهاء المهام غير المتزامنة بعد إرسال الاستجابة. في Next.js وVercel، يتم تحقيق ذلك باستخدام أداة أساسية تسمى waitUntil(promise)، والتي تمدد عمر استدعاء بلا خادم حتى تسوية جميع الوعود الممررة إلى 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.0أصبحت after مستقرة.
v15.0.0-rcتم تقديم unstable_after.