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