هذا المقال يتطلب مستوى محترف — مفترض إنك تعرف فعليًا CommonJS vs ESM، شغّلت webpack --analyze قبل كده، وفاهم إن minification مش هو Tree Shaking.
لو bundle الإنتاج بتاعك 892KB gzipped رغم إن المستخدم بيستعمل 3 شاشات بس من الـ 40 شاشة، المشكلة مش في حجم المكتبات. المشكلة إن Webpack بيشوف 73% من الكود ومش قادر يثبت إنه "آمن للحذف". في المقال ده هتفهم بالظبط ليه بيحصل ده، وهتشيل 340KB من bundle حقيقي بدون ما تلمس سطر كود تطبيقي واحد.
ليه Bundle بتاعك متخم رغم إنك "بس بتعمل import واحد"
الافتراض اللي بيخدع الناس
أغلب المطورين فاكرين إن import { Button } from 'ui-kit' بتجيب الـ Button بس. ده مش صحيح. الـ bundler مش بيقرر بناءً على اسم الـ import — بيقرر بناءً على هل قدر يثبت إن باقي الـ exports من ui-kit "مفيش حد بيستخدمها وكمان مفيش side effects".
الكلمة المفتاحية هنا: "يثبت". لو في أي شك، الـ bundler بيحتفظ بالكود. وفي العادة، بيكون عنده شك.
مثال للمبتدئ: حكاية المخبز
تخيّل مخبز بيبيع 50 صنف. لما زبون يطلب رغيف عيش، الخباز عنده اختياران:
- يجيب الرغيف بس ويسلّمه — لكن لازم يتأكد الأول إن باقي الـ 49 صنف "محدش بيطلبهم وكمان مفيش حد قال يمسك الفرن مفتوح علشانهم".
- لو مش متأكد، يجيب الـ 50 صنف كلهم ويسلّمهم للزبون — أأمن، لكن أتقل بكتير.
Webpack هو الخباز. ولو لقى أي صنف مكتوب جنبه "ممكن يحرّك حاجة في المطبخ لما تلمسه" — هيجيب كل حاجة. الكلام ده اسمه التقني side effects.
المفهوم العلمي: ESM Static Analysis
Tree Shaking مش فيتشر سحري. هو نتيجة طبيعية لطريقة عمل ECMAScript Modules. الـ ES Modules ليها 3 خصائص بتخلّي الـ static analysis ممكن:
- Top-level only: مفيش
importجوّا function أو if branch. كل الـ imports بتتحدد وقت compile. - Immutable bindings: لما تعمل
import { x }، الـ x ده live binding مش value copy. - No dynamic resolution: مفيش
require(variable)زي CommonJS.
الـ bundler بيستفيد من ده عشان يبني module graph ويعمل dead code elimination على الـ exports اللي مفيش حد بيوصل لها. ده موثّق في الـ Webpack Tree Shaking guide وفي Rollup docs.
الخطوة 1: شغّل sideEffects flag في package.json
ده أهم سطر هتكتبه النهارده. بدونه، Webpack بيفترض إن كل module في الـ dependency tree ممكن يكون عنده side effects، ويرفض يشيل أي حاجة.