ModuleConcatenationPlugin
في الإصدارات القديمة، كان أحد الجوانب السلبية في bundling داخل webpack أن كل module داخل bundle يُغلّف داخل function closure مستقل. هذه الدوال الإضافية تجعل تنفيذ JavaScript أبطأ في المتصفح. بالمقارنة، أدوات مثل Closure Compiler وRollupJS تقوم بما يسمى hoisting أو concatenation لنطاق كل modules داخل closure واحد، وهذا يساعد الكود على التنفيذ بسرعة أعلى في المتصفح.
يفعّل هذا plugin السلوك نفسه داخل webpack. افتراضيًا، يكون هذا plugin مفعّلًا في وضع production، ومعطلًا في غير ذلك. إذا أردت تعطيل هذا التحسين في وضع production، اضبط خيار optimization.concatenateModules على false. ولتفعيل هذا السلوك في أوضاع أخرى، يمكنك إضافة ModuleConcatenationPlugin يدويًا أو استخدام خيار optimization.concatenateModules:
new webpack.optimize.ModuleConcatenationPlugin();يُسمى سلوك الدمج هذا "scope hoisting".
يعتمد scope hoisting تحديدًا على صيغة ECMAScript Modules. لذلك قد يرجع webpack إلى bundling العادي حسب نوع modules التي تستخدمها، وبحسب شروط أخرى.
حالات إيقاف التحسين
كما يشرح المقال، يحاول webpack تطبيق scope hoisting جزئيًا. يمكنه دمج modules داخل نطاق واحد، لكنه لا يستطيع فعل ذلك في كل الحالات. إذا لم يستطع webpack دمج module، فهناك نتيجتان محتملتان: Prevent أو Root. تعني Prevent أن module يجب أن يبقى في نطاق مستقل. وتعني Root أن webpack سينشئ مجموعة modules جديدة. تحدد الشروط التالية النتيجة:
| الشرط | النتيجة |
|---|---|
| ليس ES6 Module | Prevent |
| مستورد بواسطة غير import | Root |
| مستورد من chunk آخر | Root |
| مستورد بواسطة عدة module groups أخرى | Root |
مستورد باستخدام import() | Root |
متأثر بـ ProvidePlugin أو يستخدم module | Prevent |
| مقبول من HMR | Root |
يستخدم eval() | Prevent |
| موجود في عدة chunks | Prevent |
export * from "cjs-module" | Prevent |
خوارزمية تجميع modules
يوضح pseudo JavaScript التالي الخوارزمية:
function tryToAdd(group, module) {
if (group.has(module)) {
return true;
}
if (!hasPreconditions(module)) {
return false;
}
const nextGroup = group;
const result = module.dependents.reduce(
(check, dependent) => check && tryToAdd(nextGroup, dependent),
true,
);
if (!result) {
return false;
}
for (const dependency of module.dependencies) {
tryToAdd(group, dependency);
}
group.merge(nextGroup);
return true;
}
for (const module of modules) {
const group = new ModuleGroup({
root: module,
});
for (const dependency of module.dependencies) {
tryToAdd(group, dependency);
}
if (group.modules.length > 1) {
orderedModules = topologicalSort(group.modules);
concatenatedModule = new ConcatenatedModule(orderedModules);
chunk.add(concatenatedModule);
for (const groupModule of orderedModules) {
chunk.remove(groupModule);
}
}
}تصحيح حالات إيقاف التحسين
عند استخدام webpack CLI، يعرض flag --stats-optimization-bailout أسباب إيقاف التحسين. وعند استخدام ملف إعدادات webpack، أضف الخيار التالي إلى كائن stats:
export default {
// ...
stats: {
// Display bailout reasons
optimizationBailout: true,
},
};


