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 . |