المستوى: متوسط (Intermediate) — الافتراض إنك بتشتغل على تطبيق ويب حديث ببندلر زي Vite أو webpack 5، وبتخدم على HTTP/2.
لو أول تحميل لموقعك بيبعت ملف JavaScript أكبر من ميجابايت، المستخدم بيبص على شاشة بيضا ثواني قبل ما يتفاعل. تقسيم الكود مع Tree Shaking بيقدر ينزّل أول تحميل من 1.4 ميجابايت لـ 280 كيلوبايت تقريبًا، من غير ما تحذف ولا ميزة واحدة.
تقسيم الكود وTree Shaking: صغّر حزمة JavaScript وسرّع أول تحميل
المشكلة باختصار
البندلر افتراضيًا بيجمّع كودك وكل مكتباتك في حزمة واحدة كبيرة. المتصفح لازم ينزّلها ويحللها ويشغّلها قبل ما الصفحة تشتغل. النتيجة: زمن تفاعل بطيء، خصوصًا على موبايل متوسط وشبكة 4G. المشكلة مش في السيرفر، المشكلة إنك بتبعت كود المستخدم مش محتاجه دلوقتي.
تقسيم الكود (Code Splitting): المفهوم بمثال ثم بدقة
تخيّل مطعم بيديك قائمة 200 صفحة أول ما تقعد، وانت عايز تطلب حاجة واحدة. ده اللي بيحصل مع الحزمة الواحدة الكبيرة: بتحمّل كل صفحات التطبيق عشان تعرض صفحة واحدة. تقسيم الكود بيقلب ده: يديك صفحة القائمة اللي محتاجها دلوقتي بس، والباقي يجيبه لما تطلبه.
علميًا: تقسيم الكود هو تقطيع الحزمة الواحدة إلى عدة ملفات (chunks) يتم تحميلها عند الطلب بدل تحميلها كلها مقدمًا. أشهر طريقة هي التقسيم على مستوى المسار (route-based) أو المكوّن الثقيل، باستخدام الاستيراد الديناميكي import() اللي بيرجّع Promise ويخلّي البندلر يعمل chunk منفصل تلقائيًا.
// بدل الاستيراد الثابت اللي بيدخل في الحزمة الرئيسية:
// import Editor from "./Editor";
// حمّل المكوّن الثقيل وقت الحاجة بس:
const Editor = React.lazy(() => import("./Editor"));
function Page() {
return (
<Suspense fallback={<p>جارِ التحميل...</p>}>
<Editor />
</Suspense>
);
}
Tree Shaking: بمثال ثم بدقة
تخيّل إنك بتحزّم شنطة سفر: بتاخد الهدوم اللي هتلبسها بس، وتسيب الباقي في الدولاب. Tree Shaking بيعمل نفس الحاجة مع كودك: بيسيب أي كود مستورد بس مش مستخدم ومبياخدوش في الحزمة النهائية.
علميًا: Tree Shaking هو حذف الكود الميت (dead code elimination) بالاعتماد على الطبيعة الساكنة لوحدات ES (import/export). البندلر بيحلل الرسم البياني للاستيرادات ويشيل الصادرات اللي محدش بيستخدمها. الشرط إنك تستخدم ESM مش CommonJS، وتستورد الدوال بالاسم بدل المكتبة كلها.
// غلط: بيسحب مكتبة lodash كلها (~70KB مصغّرة):
import _ from "lodash";
_.debounce(fn, 200);
// صح: بيسحب الدالة المطلوبة بس، والباقي يتشال:
import debounce from "lodash/debounce";
debounce(fn, 200);