الرئيسيةمن أناالدوراتالمدونةسوق الأوامرالمناهج والباقاتالشركاء

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • سوق الأوامر
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
Optimizing بالعربي

تقسيم الكود وTree Shaking: صغّر حزمة JavaScript وسرّع أول تحميل

متوسط6 أغسطس 20264 دقائق قراءة
تقسيم الكود وTree Shaking: صغّر حزمة JavaScript وسرّع أول تحميل

المستوى: متوسط (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 منفصل تلقائيًا.

JavaScript
// بدل الاستيراد الثابت اللي بيدخل في الحزمة الرئيسية:
// 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، وتستورد الدوال بالاسم بدل المكتبة كلها.

JavaScript
// غلط: بيسحب مكتبة lodash كلها (~70KB مصغّرة):
import _ from "lodash";
_.debounce(fn, 200);

// صح: بيسحب الدالة المطلوبة بس، والباقي يتشال:
import debounce from "lodash/debounce";
debounce(fn, 200);

وفي package.json علّم مكتباتك النقية بإنها بدون آثار جانبية عشان البندلر يقدر يشيل غير المستخدم بأمان:

JSON
{
  "sideEffects": false
}

خطوات عملية تطبّقها النهاردة

  1. حلّل حزمتك بصريًا وشوف الأكبر: npx vite-bundle-visualizer أو webpack-bundle-analyzer.
  2. حدّد الأجزاء الثقيلة غير الحرجة (محرر نصوص، مكتبة رسوم بيانية، صفحة إعدادات نادرة).
  3. لفّ كل جزء منهم في import() ديناميكي عشان يتفصل في chunk لوحده.
  4. افصل مكتبات الطرف الثالث في chunk ثابت (vendor) عشان الكاش يفضل شغّال بين الإصدارات.
  5. ابنِ وقيس الفرق: npx vite build وقارن أحجام الملفات قبل وبعد.
JavaScript
// vite.config.js — افصل vendor والرسوم في chunks مستقلة
export default {
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ["react", "react-dom"],
          charts: ["recharts"]
        }
      }
    }
  }
};

سيناريو واقعي: تطبيق لوحة تحكم فيه محرر ومكتبة رسوم بيانية، حزمته الأولى 1.4 ميجابايت. بعد فصل المحرر والرسوم في chunks تُحمّل عند الطلب، وتطبيق Tree Shaking على lodash، نزل أول تحميل لـ 280 كيلوبايت — انخفاض حوالي 80%. الأرقام دي تقديرية وبتختلف حسب مكتباتك، لكن الترتيب واقعي. على موبايل متوسط وشبكة 4G مخنوقة، زمن التفاعل (TTI) نزل تقديريًا من نحو 3.2 ثانية لـ 0.9 ثانية.

الـ trade-offs اللي لازم تاخد بالك منها

بتكسب أول تحميل أخف، بتخسر إن عدد الطلبات بيزيد. مع HTTP/2 ده مش مشكلة غالبًا بسبب الـ multiplexing، لكن مع HTTP/1.1 ممكن كتر الملفات الصغيرة يبطّئ. الـ trade-off التاني: التقسيم الزيادة ممكن يعمل سلسلة تحميل متتابعة (waterfall) لو جزء بيستنى جزء. وأي حدود lazy بتضيف حالة تحميل (spinner) وتعقيد بسيط في الكود. أما Tree Shaking فبيفشل بصمت لو استوردت بـ CommonJS أو نسيت ضبط sideEffects، فيفضل الكود الميت في الحزمة وانت فاكره اتشال.

متى لا تستخدم هذه الطريقة

لو تطبيقك صغير وحزمته أصلاً أقل من 100 كيلوبايت، التقسيم بيضيف تعقيد بدون مكسب حقيقي. ومتعملش lazy للكود الحرج فوق الطية (above-the-fold) لأنك هتضيف spinner مكان محتوى المفروض يظهر فورًا. ولو البنية التحتية عندك على HTTP/1.1 من غير CDN حديث، كتر الـ chunks الصغيرة ممكن يضرّك أكتر مما ينفع.

الخطوة التالية

شغّل npx vite-bundle-visualizer على مشروعك دلوقتي، دوّر على أكبر جزء غير حرج، لفّه في import() ديناميكي، وابنِ وقارن. لو أول تحميل نزل بشكل ملحوظ، كمّل على باقي الأجزاء الثقيلة واحدًا واحدًا.

المصادر

  • webpack — Code Splitting: https://webpack.js.org/guides/code-splitting/
  • webpack — Tree Shaking وsideEffects: https://webpack.js.org/guides/tree-shaking/
  • MDN — الاستيراد الديناميكي import(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
  • web.dev — Reduce JavaScript payloads with code splitting: https://web.dev/articles/reduce-javascript-payloads-with-code-splitting
  • web.dev — Remove unused code: https://web.dev/articles/remove-unused-code
  • Vite — Build Options وrollupOptions: https://vitejs.dev/config/build-options.html
  • Rollup — Tree-shaking: https://rollupjs.org/introduction/#tree-shaking

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة