Turbopack chunking: طلبات أقل أم كود أقل؟
في 3 سبتمبر 2026 نشر فريق Turbopack في Vercel مقالًا بعنوان "How Turbopack chunks your JavaScript"، يشرح كيف يقرّر الـ bundler توزيع كود التطبيق على ملفات chunks، ولماذا لا توجد قسمة واحدة صحيحة. الأهم أنه يكشف المعادلة التي كانت تعمل بصمت في كل build، ويفتحها للضبط عبر إعدادات تجريبية في Next.js 16.3.
المشكلة: هدفان يتنازعان
أبسط الحلول أن يُجمع كل الكود في chunk واحد: طلب شبكة واحد، وكل زيارة بعد الأولى تصيب الـ cache. الثمن أن صفحة لا تحتاج شيئًا تحمّل كود الموقع كله، وكلما كبر المشروع صار كل تحميل أثقل.
الحل المعاكس هو chunk لكل صفحة. لا زيادة في الكود المُرسل، لكن مكوّنًا مشتركًا مثل <Footer /> ينتهي داخل ملف كل صفحة، فيُحمَّل أربع مرات لزائر فتح أربع صفحات.
والحل الثالث — chunk لكل module — يلغي التكرار تمامًا ويستبدله بمئات الطلبات الصغيرة. صحيح أن HTTP/2 خفّض تكلفة الطلب، لكنه لم يُلغِها، كما أن خوارزميات الضغط مثل gzip تعمل بكفاءة أقل على ملفات صغيرة متعددة لأنها لا ترى التكرار خارج حدود الملف الواحد.
ما الذي تغيّر: الدمج كقرار احتمالي
يعالج Turbopack هذا بدمج chunks صغيرة في أكبر منها، لكن داخل ما يسميه chunk group فقط — أي مجموعة الملفات التي تُحمَّل معًا لمسار واحد. الدمج داخل المجموعة آمن لأنه لا يضيف كودًا لم تكن الصفحة ستحمّله أصلًا.
يبقى السؤال: متى يستحق الدمج؟ الجواب في المقال احتمالي بالكامل. عند التفكير في دمج chunk اسمه A مع آخر اسمه B، يحسب Turbopack عدد المجموعات التي تستخدم A وحده، وB وحده، وكليهما معًا، ثم يوازن الربح بالخسارة. الدمج يربح دائمًا إذا غادر الزائر بعد صفحة واحدة، ولا يربح عند التنقل إلا إذا كانت الصفحة الثانية تحتاج الاثنين. وللترجيح بين الحالتين يفترض المحرك أن ثلثي الجلسات صفحة واحدة فقط.
الأرقام التي نشرها الفريق من زيارة فعلية لـ nextjs.org عبر ثماني خطوات تنقّل توضّح المقايضة:
- بلا دمج: 561.6 KiB في 96 طلبًا
- الإعدادات الافتراضية: 554.8 KiB في 38 طلبًا
- دمج كل مجموعة في chunk واحد: 610.0 KiB في 15 طلبًا
الافتراضي قلّص الطلبات إلى أقل من النصف وشحن كودًا أقل قليلًا. الدمج الأقصى خفّض الطلبات أكثر، لكنه شحن نحو 10% كودًا إضافيًا عبر الجلسة.
المعادلة صارت قابلة للضبط
القيد الحقيقي أن الدمج يُقرَّر وقت الـ build، قبل أن يزور أحد الموقع، وبافتراضات عامة عن سلوك الزوار. إعدادات Next.js 16.3 التجريبية تعالج الطرفين:
import type { NextConfig } from 'next'
const nextConfig = {
experimental: {
turbopackChunking: {
// يُصدر النسخ غير المدموجة بجانب المدموجة
generateComponentChunks: true,
minComponentChunkSize: 20000,
// 0.67 افتراضيًا — bounce rate تقدير جيد
firstPageLoadPriority: 0.5,
// الصفحات التي يبدأ منها الزوار عادة
priorityRoutes: [/^\/$/, /^\/pricing/],
minChunkSize: 50000,
maxChunkCountPerGroup: 40,
},
turbopackCjsTreeShaking: true,
turbopackSharedRuntime: true,
},
} satisfies NextConfig
export default nextConfiggenerateComponentChunks هو التغيير الأذكى: يُصدر كل chunk مدموج نسخه المكوِّنة إلى جانبه، فيختار الـ runtime وقت الطلب الأرخص — الملف المدموج، أو القطع الناقصة فقط. والعكس صحيح أيضًا: ما حُمِّل ضمن دمج سابق لا يُحمَّل مرة ثانية عند التنقل.
أما firstPageLoadPriority وpriorityRoutes فينقلان الافتراض من تقدير عام إلى بيانات موقعك. إن كان الـ bounce rate مرتفعًا فالأولوية للتحميل الأول، وإن كان الزوار يتنقلون كثيرًا فالعكس. وأعلن الفريق كذلك عن clusters لتجميع المسارات التي تُزار معًا عادة.
إلى جانب ذلك: turbopackSharedRuntime يستبدل الـ runtime المكرر لكل صفحة بواحد مشترك، ويوفّر طلبًا حاجبًا ونحو 10 KB في كل تنقّل بعد الأول، وturbopackCjsTreeShaking يمدّ إزالة الكود غير المستخدم إلى modules بصيغة CJS بعدما كانت محصورة في ESM.
تحفظات عملية
هذه الإعدادات تجريبية، وتوثيق Next.js يذكر صراحة أنها غير موصى بها للإنتاج بعد. الأحجام في الإعدادات تُقاس بالبايت من كود غير مضغوط وغير مصغّر — تقريبًا خمسة أضعاف حجم المخرَج النهائي. والأهم أن أرقام nextjs.org ليست أرقامك: موقع محتوى يتنقل فيه الزائر كثيرًا يستفيد من دمج أقل، وصفحة هبوط واحدة تستفيد من العكس تمامًا. القياس قبل الضبط، ثم القياس بعده.
الخلاصة
تقسيم الـ chunks ليس تفصيلًا داخليًا في الـ bundler، بل رهان على سلوك زوارك. الجديد في Next.js 16.3 أنه يسمح باستبدال تخمين المحرك ببيانات فعلية، ويعيد جزءًا من القرار من وقت الـ build إلى الـ runtime حيث تُعرف حالة الـ cache الحقيقية.
المصدر الأساسي: How Turbopack chunks your JavaScript — وللسياق حول أدوات البناء الأسرع في نفس الإصدار: TypeScript 7 ومترجمه الأصلي.