Webpack 5 release
تم إصدار Webpack 4 في فبراير 2018. منذ ذلك الحين قمنا بشحن الكثير من المميزات دون إحداث تغييرات جذرية (breaking changes). نحن نعلم أن الناس يكرهون التغييرات الكبيرة التي تصاحبها تغييرات جذرية. خاصة مع webpack، الذي عادة ما يتعامل معه الناس مرتين فقط في السنة، وفي بقية الوقت "يعمل ببساطة". لكن شحن الميزات دون تغييرات جذرية له تكلفة أيضًا: لا يمكننا إجراء تحسينات كبيرة على واجهة برمجة التطبيقات (API) أو البنية المعمارية.
لذا من وقت لآخر، نصل إلى نقطة تتراكم فيها الصعوبات ونُجبر على إجراء تغييرات جذرية لتجنب إفساد كل شيء. هذا هو الوقت المناسب لإصدار رئيسي جديد (major version). لذلك يحتوي webpack 5 على هذه التحسينات المعمارية والميزات التي لم يكن من الممكن تنفيذها بدونها.
كان الإصدار الرئيسي أيضًا فرصة لمراجعة بعض الإعدادات الافتراضية ومواءمتها مع المقترحات والمواصفات التي ظهرت في غضون ذلك.
لذا تم اليوم (2020-10-10) إطلاق webpack 5.0.0، لكن هذا لا يعني أنه مكتمل، أو خالٍ من الأخطاء، أو حتى مكتمل الميزات. كما حدث مع webpack 4، نواصل التطوير من خلال إصلاح المشاكل وإضافة الميزات. في الأيام القادمة من المحتمل أن يكون هناك الكثير من إصلاحات الأخطاء. ستأتي الميزات لاحقًا.
أسئلة شائعة
إذن ماذا يعني هذا الإصدار؟
يعني أننا انتهينا من إجراء التغييرات الجذرية. تم إجراء العديد من عمليات إعادة الهيكلة (refactoring) لرفع مستوى البنية وإنشاء قاعدة جيدة للميزات المستقبلية (والميزات الحالية).
إذن متى يحين وقت الترقية؟
يعتمد الأمر. هناك فرصة جيدة أن تفشل الترقية وقد تحتاج إلى المحاولة للمرة الثانية أو الثالثة. إذا كنت منفتحًا على ذلك، فحاول الترقية الآن وقدم ملاحظاتك إلى webpack والإضافات (plugins) والمحملات (loaders). نحن حريصون على إصلاح تلك المشاكل. يجب أن يبدأ شخص ما وستكون أنت من أوائل المستفيدين منه.
تحديث الرعاية (Sponsoring Update)
يعتمد Webpack بالكامل على الرعاية. إنه غير مرتبط (أو مدفوع الأجر) بشركة كبيرة مثل بعض مشاريع المصادر المفتوحة الأخرى. يتم توزيع 99% من أرباح الرعاية على المساهمين والمشرفين بناءً على المساهمات التي يقومون بها. نحن نؤمن باستثمار الأموال نحو جعل webpack أفضل.
ولكن هناك جائحة، والشركات لم تعد منفتحة كثيرًا على الرعاية كما كانت. يعاني Webpack في ظل هذه الظروف أيضًا (مثل العديد من الشركات والأشخاص الآخرين).
لم نتمكن أبدًا من الدفع لمساهمينا المبلغ الذي نعتقد أنهم يستحقونه، ولكن الآن ليس لدينا سوى نصف الأموال المتاحة، لذا نحن بحاجة إلى إجراء خفض أكثر جدية. حتى يتحسن الوضع، سندفع فقط للمساهمين والمشرفين عن الأيام العشرة الأولى من كل شهر. أما الأيام المتبقية فيمكنهم العمل بشكل تطوعي، أو بأجر من صاحب عملهم، أو العمل على شيء آخر، أو أخذ بعض أيام الإجازة. يتيح لنا ذلك الدفع مقابل عملهم في الأيام العشرة الأولى بما يعادل بشكل أكبر الوقت المستثمر.
أكبر كلمة "شكرًا" تذهب إلى trivago التي كانت ترعى webpack بمبلغ ضخم على مدار السنوات الثلاث الماضية. للأسف هم غير قادرين على الاستمرار في رعايتهم هذا العام، حيث تضرروا بشدة من Covid-19. آمل أن تتقدم شركة أخرى وتحذو حذو هذه الخطوات (العملاقة).
شكرًا لـ جميع الرعاة.
الاتجاه العام
يركز هذا الإصدار على ما يلي:
- تحسين أداء البناء باستخدام التخزين المؤقت المستمر (Persistent Caching).
- تحسين التخزين المؤقت طويل المدى (Long Term Caching) بخوارزميات وافتراضيات أفضل.
- تحسين حجم الحزمة (bundle size) بفضل Tree Shaking وتوليد أكواد أفضل.
- تحسين التوافق مع منصة الويب.
- تنظيف الهياكل الداخلية التي تُركت في حالة غريبة أثناء تنفيذ الميزات في الإصدار 4 دون إدخال أي تغييرات جذرية.
- التحضير للميزات المستقبلية عن طريق إدخال تغييرات جذرية الآن، مما يسمح لنا بالبقاء على الإصدار 5 لأطول فترة ممكنة.
دليل الترحيل (Migration Guide)
انظر هنا للحصول على دليل الترحيل
تغييرات رئيسية: الإزالات
إزالة العناصر المهملة (Deprecated Items)
تمت إزالة جميع العناصر التي تم إهمالها في الإصدار 4.
الترحيل: تأكد من أن بناء webpack 4 الخاص بك لا يطبع تحذيرات الإهمال (deprecation warnings).
إليك بعض الأشياء التي تمت إزالتها ولكن لم تكن تحتوي على تحذيرات إهمال في الإصدار 4:
- يجب الآن تمرير وسيط واحد فقط لـ IgnorePlugin و BannerPlugin، يمكن أن يكون كائنًا (object)، أو سلسلة نصية (string)، أو دالة (function).
رموز الإهمال (Deprecation codes)
تتضمن الإهمالات الجديدة رمز إهمال بحيث يسهل الإشارة إليها.
بنية جمل مهملة (Syntax deprecated)
تم إهمال require.include وسيصدر تحذيرًا بشكل افتراضي عند استخدامه.
يمكن تغيير السلوك باستخدام Rule.parser.requireInclude إلى مسموح به (allowed)، مهمل (deprecated)، أو معطل (disabled).
إزالة تعويضات Node.js التلقائية (Automatic Node.js Polyfills Removed)
في الأيام الأولى، كان هدف webpack هو السماح بتشغيل معظم وحدات Node.js في المتصفح، ولكن المشهد تغير وأصبحت العديد من الوحدات تُكتب الآن بشكل أساسي لأغراض الواجهة الأمامية. يأتي Webpack <= 4 مع تعويضات (polyfills) للعديد من الوحدات الأساسية لـ Node.js، والتي يتم تطبيقها تلقائيًا بمجرد استخدام أي وحدة من الوحدات الأساسية (مثل وحدة crypto).
في حين أن هذا يجعل استخدام الوحدات المكتوبة لـ Node.js أسهل، إلا أنه يضيف هذه التعويضات الضخمة إلى الحزمة. في كثير من الحالات، تكون هذه التعويضات غير ضرورية.
يتوقف Webpack 5 عن إضافة التعويضات لهذه الوحدات الأساسية تلقائيًا ويركز على الوحدات المتوافقة مع الواجهة الأمامية. هدفنا هو تحسين التوافق مع منصة الويب، حيث لا تتوفر الوحدات الأساسية لـ Node.js.
الترحيل:
- حاول استخدام الوحدات المتوافقة مع الواجهة الأمامية كلما أمكن ذلك.
- من الممكن إضافة تعويض (polyfill) يدويًا لوحدة أساسية في Node.js. ستعطي رسالة الخطأ تلميحًا حول كيفية تحقيق ذلك.
- لمؤلفي الحزم: استخدم حقل
browserفيpackage.jsonلجعل الحزمة متوافقة مع الواجهة الأمامية. قدم تطبيقات/تبعيات (implementations/dependencies) بديلة للمتصفح.
تغييرات رئيسية: التخزين المؤقت طويل المدى (Long Term Caching)
الحزم، ومعرفات الوحدات، وأسماء الصادرات الحتمية (Deterministic)
تمت إضافة خوارزميات جديدة للتخزين المؤقت طويل المدى. تم تمكينها بشكل افتراضي في وضع الإنتاج (production mode).
chunkIds: "deterministic"
moduleIds: "deterministic"
mangleExports: "deterministic"
تقوم الخوارزميات بتعيين معرفات رقمية قصيرة (3 أو 5 أرقام) للوحدات والحزم، وأسماء قصيرة (حرفان) للصادرات بطريقة حتمية (deterministic). هذا يمثل مقايضة (trade-off) بين حجم الحزمة والتخزين المؤقت طويل المدى.
يقوم moduleIds/chunkIds/mangleExports: false بتعطيل السلوك الافتراضي ويمكن للمرء توفير خوارزمية مخصصة عبر إضافة (plugin). لاحظ أنه في webpack 4، كان استخدام moduleIds/chunkIds: false بدون إضافة مخصصة يؤدي إلى بناء يعمل، بينما في webpack 5 يجب عليك توفير إضافة مخصصة.
الترحيل: من الأفضل استخدام القيم الافتراضية لـ chunkIds و moduleIds و mangleExports. يمكنك أيضًا اختيار الافتراضيات القديمة chunkIds: "size", moduleIds: "size", mangleExports: "size"، سيؤدي هذا إلى إنشاء حزم أصغر، ولكنه سيبطل صلاحيتها (invalidate) بشكل متكرر عند التخزين المؤقت.
ملاحظة: في webpack 4، أدت معرفات الوحدات المجزأة (hashed module ids) إلى انخفاض أداء gzip. كان هذا مرتبطًا بتغير ترتيب الوحدات وتم إصلاحه.
ملاحظة: في webpack 5، تم تفعيل المعرفات deterministic بشكل افتراضي في وضع الإنتاج.
التجزئة الحقيقية للمحتوى (Real Content Hash)
سيستخدم Webpack 5 تجزئة (hash) حقيقية لمحتوى الملف عند استخدام [contenthash] الآن. في السابق كان يستخدم "فقط" تجزئة للبنية الداخلية.
يمكن أن يكون لهذا تأثير إيجابي على التخزين المؤقت طويل المدى عندما يتم تغيير التعليقات فقط أو إعادة تسمية المتغيرات. هذه التغييرات غير مرئية بعد التصغير (minimizing).
تغييرات رئيسية: دعم التطوير (Development Support)
معرفات الحزم المسماة (Named Chunk IDs)
تم تمكين خوارزمية جديدة لمعرف الحزمة المسمى بشكل افتراضي في وضع التطوير (development mode) لمنح الحزم (وأسماء الملفات) أسماء قابلة للقراءة البشرية.
يتم تحديد معرف الوحدة (Module ID) من خلال مسارها بالنسبة إلى الـ context.
يتم تحديد معرف الحزمة (Chunk ID) من خلال محتوى الحزمة.
لذلك لم تعد بحاجة إلى استخدام import(/* webpackChunkName: "name" */ "module") لأغراض تصحيح الأخطاء (debugging).
ولكن سيظل من المنطقي استخدامها إذا كنت ترغب في التحكم في أسماء الملفات لبيئات الإنتاج.
من الممكن استخدام chunkIds: "named" في الإنتاج، ولكن تأكد من عدم الكشف عن معلومات حساسة حول أسماء الوحدات عن طريق الخطأ.
الترحيل: إذا كنت تكره تغيير أسماء الملفات في التطوير، يمكنك تمرير chunkIds: "natural" لاستخدام الوضع الرقمي القديم.
Module Federation
يضيف Webpack 5 ميزة جديدة تسمى "Module Federation"، والتي تسمح لعدة بنيات (builds) webpack بالعمل معًا. من منظور وقت التشغيل (runtime)، ستتصرف الوحدات من عمليات البناء المتعددة وكأنها رسم بياني متصل ضخم للوحدات. من منظور المطور، يمكن استيراد الوحدات من عمليات بناء بعيدة (remote) محددة واستخدامها بأقل قدر من القيود.
لمزيد من التفاصيل انظر هذا الدليل المنفصل.
تغييرات رئيسية: ميزات منصة الويب الجديدة
وحدات JSON (JSON modules)
تتوافق وحدات JSON الآن مع الاقتراح وتصدر تحذيرًا عند استخدام تصدير غير افتراضي (non-default export). لم يعد لوحدات JSON صادرات مسماة (named exports) عند الاستيراد من وحدة ECMAScript صارمة.
الترحيل: استخدم التصدير الافتراضي (default export).
حتى عند استخدام التصدير الافتراضي، يتم إسقاط الخصائص غير المستخدمة بواسطة تحسين optimization.usedExports ويتم تغيير الخصائص (mangled) بواسطة تحسين optimization.mangleExports.
من الممكن تحديد محلل JSON مخصص في Rule.parser.parse لاستيراد ملفات تشبه JSON (مثل toml، yaml، json5، إلخ).
import.meta
import.meta.webpackHotهو اسم مستعار لـmodule.hotالمتاح أيضًا في ESM الصارم.import.meta.webpackهو الإصدار الرئيسي لـ webpack كـ رقم.import.meta.urlهو رابطfile:للملف الحالي (على غرار__filenameولكن كرابط ملف).
وحدات الأصول (Asset modules)
يتمتع Webpack 5 الآن بدعم محلي للوحدات التي تمثل الأصول (assets). ستقوم هذه الوحدات إما بإخراج ملف إلى مجلد المخرجات (output folder) أو حقن DataURI في حزمة javascript. في كلتا الحالتين تمنحك رابط URL للعمل به.
يمكن استخدامها عبر طرق متعددة:
import url from "./image.png"وتعيينtype: "asset"فيmodule.rulesعند مطابقة مثل هذا الاستيراد. (الطريقة القديمة)new URL("./image.png", import.meta.url)(الطريقة الجديدة)
تم اختيار بنية "الطريقة الجديدة" للسماح بتشغيل الكود بدون محزم (bundler) أيضًا. تتوفر هذه البنية أيضًا في وحدات ECMAScript المحلية في المتصفح.
دعم Worker المحلي
عند الجمع بين new URL للأصول مع new Worker/new SharedWorker/navigator.serviceWorker.register سيقوم webpack تلقائيًا بإنشاء نقطة دخول جديدة لـ web worker.
new Worker(new URL("./worker.js", import.meta.url))
تم اختيار البنية للسماح بتشغيل الكود بدون محزم أيضًا. تتوفر هذه البنية أيضًا في وحدات ECMAScript المحلية في المتصفح.
المعرفات المنتظمة (URIs)
يدعم Webpack 5 التعامل مع البروتوكولات في الطلبات (requests).
data:مدعوم. يدعم تشفير Base64 أو الخام (raw). يمكن تعيين Mimetype للمحملات ونوع الوحدة فيmodule.rules. مثال:import x from "data:text/javascript,export default 42"file:مدعوم.http(s):مدعوم، لكنه يتطلب التفعيل عبرnew webpack.experiments.schemesHttp(s)UriPlugin()- افتراضيًا عند استهداف "web"، تؤدي عناوين URI هذه إلى طلبات لموارد خارجية (وهي externals).
الأجزاء (Fragments) في الطلبات مدعومة: مثال: ./file.js#fragment
الوحدات غير المتزامنة (Async modules)
يدعم Webpack 5 ما يسمى "الوحدات غير المتزامنة". هي الوحدات التي لا يتم تقييمها بشكل متزامن، بل هي غير متزامنة وتعتمد على الوعود (Promise-based).
يتم التعامل مع استيرادها عبر import تلقائيًا ولا يلزم وجود بنية إضافية والفرق بالكاد يمكن ملاحظته.
استيرادها عبر require() سيعيد Promise يحل للصادرات (exports).
في webpack، هناك عدة طرق لامتلاك وحدات غير متزامنة:
- externals غير متزامنة
- وحدات WebAssembly في المواصفات الجديدة
- وحدات ECMAScript التي تستخدم Top-Level-Await
الخارجيون (Externals)
يضيف Webpack 5 أنواعًا إضافية للخارجيين لتغطية المزيد من التطبيقات:
promise: تعبير يتم تقييمه كـ Promise. الوحدة الخارجية هي وحدة غير متزامنة وتُستخدم القيمة التي تم حلها كصادرات للوحدة.
import: تُستخدم import() المحلية لتحميل الطلب المحدد. الوحدة الخارجية هي وحدة غير متزامنة.
module: لم يتم تنفيذها بعد، ولكن من المخطط تحميل الوحدات عبر import x from "...".
script: تقوم بتحميل عنوان url عبر علامة <script> وتحصل على الصادرات من متغير عام (واختياريًا خصائص منه). الوحدة الخارجية هي وحدة غير متزامنة.
تغييرات رئيسية: ميزات نظام Node.js البيئي الجديد
التحليل (Resolving)
حقل exports و imports في package.json مدعوم الآن.
Yarn PnP مدعوم محليًا.
انظر لمزيد من التفاصيل في صادرات الحزمة (package exports).
تغييرات رئيسية: تجربة التطوير (Development Experience)
هدف (target) محسن
يسمح Webpack 5 بتمرير قائمة بالأهداف (targets) ويدعم أيضًا إصدارات الهدف.
أمثلة: target: "node14" target: ["web", "es2020"]
هذا يمكننا من تزويد webpack بجميع المعلومات التي يحتاجها لتحديد:
- آلية تحميل الحزمة (chunk loading mechanism)، و
- البنية المدعومة مثل الدوال السهمية (arrow functions)
الإحصائيات (Stats)
تم تحسين تنسيق الإحصائيات من حيث قابلية القراءة والإسهاب. تم تحسين الإعدادات الافتراضية لتكون أقل إسهابًا ومناسبة أيضًا لعمليات البناء الكبيرة.
- يتم إخفاء علاقات الحزم (Chunk relations) افتراضيًا الآن. يمكن تبديل هذا باستخدام
stats.chunkRelations. - تميز الإحصائيات الآن بين
files(الملفات) وauxiliaryFiles(الملفات المساعدة). - تخفي الإحصائيات معرفات الوحدات والحزم افتراضيًا الآن. يمكن تبديل هذا باستخدام
stats.ids. - يتم الآن فرز قائمة بجميع الوحدات حسب المسافة إلى نقطة الدخول (entrypoint). يمكن تغيير ذلك باستخدام
stats.modulesSort. - يتم الآن فرز قائمة وحدات الحزمة حسب اسم الوحدة. يمكن تغيير ذلك باستخدام
stats.chunkModulesSort. - يتم الآن فرز قائمة الوحدات المتداخلة في الوحدات المتسلسلة (concatenated modules) طوبولوجيًا. يمكن تغيير ذلك باستخدام
stats.nestedModulesSort. - تُظهر الحزم والأصول تلميحات لمعرف الحزمة الآن.
- سيتم عرض الأصول والوحدات في شجرة بدلاً من قائمة/جدول.
- يتم عرض المعلومات العامة في ملخص في النهاية الآن. يعرض إصدار webpack، واسم التكوين، وعدد التحذيرات/الأخطاء.
- يتم إخفاء التجزئة (Hash) افتراضيًا الآن. يمكن تغيير ذلك باستخدام
stats.hash. - لم يعد يظهر الطابع الزمني (Timestamp) للبناء بشكل افتراضي. يمكن تفعيله باستخدام
stats.builtAt. سيُظهر الطابع الزمني في الملخص. - لن يتم عرض التجميعات الفرعية (Child compilations) بشكل افتراضي. يمكن عرضها باستخدام
stats.children.
التقدم (Progress)
تم إجراء بعض التحسينات على ProgressPlugin والذي يُستخدم من أجل --progress بواسطة واجهة سطر الأوامر (CLI)، ولكن يمكن استخدامه أيضًا يدويًا كإضافة (plugin).
كانت تقوم فقط بحساب الوحدات المعالجة. الآن يمكنها حساب الـ entries (المدخلات)، dependencies (التبعيات)، و modules (الوحدات).
يتم عرضها جميعًا بشكل افتراضي الآن.
كانت تقوم بعرض الوحدة التي تتم معالجتها حاليًا. تسبب هذا في الكثير من مخرجات الخطأ القياسي (stderr output) وأسفر عن مشكلة في الأداء على بعض الطرفيات (consoles).
تم تعطيل هذا الآن بشكل افتراضي (خيار activeModules). وهذا يقلل أيضًا من كمية الرسائل المزعجة على الطرفية.
الآن يتم تقييد الكتابة إلى الخطأ القياسي (stderr) أثناء بناء الوحدات إلى 500 مللي ثانية.
حصل وضع ملفات التعريف (profiling mode) أيضًا على ترقية وسيعرض توقيتات رسائل التقدم المتداخلة. هذا يجعل من السهل معرفة أي إضافة تسبب مشاكل في الأداء.
يخبر الخيار المُضاف حديثًا percentBy إضافة ProgressPlugin بكيفية حساب نسبة التقدم.
new webpack.ProgressPlugin({ percentBy: "entries" });لجعل نسبة التقدم أكثر دقة، تقوم ProgressPlugin بتخزين آخر عدد إجمالي معروف للوحدات وتعيد استخدام هذه القيمة في البناء التالي. سيقوم البناء الأول بتسخين ذاكرة التخزين المؤقت ولكن البنيات التالية ستستخدم وتُحدّث هذه القيمة.
التسمية الفريدة التلقائية (Automatic unique naming)
في webpack 4، كان بإمكان أوقات تشغيل (runtimes) webpack المتعددة أن تتعارض في نفس صفحة HTML، لأنها تستخدم نفس المتغير العام (global variable) لتحميل الحزم. لإصلاح ذلك، كان من الضروري توفير اسم مخصص في تكوين output.jsonpFunction.
يقوم Webpack 5 تلقائيًا باستنتاج اسم فريد للبناء من name في package.json ويستخدم هذا كإعداد افتراضي لـ output.uniqueName.
تُستخدم هذه القيمة لجعل جميع المتغيرات العامة المتعارضة المحتملة فريدة من نوعها.
الترحيل: أزل output.jsonpFunction لصالح اسم فريد في package.json.
المسار العام التلقائي (Automatic public path)
سيقوم Webpack 5 بتحديد output.publicPath تلقائيًا كلما أمكن ذلك.
أنواع Typescript (Typescript typings)
يقوم Webpack 5 بتوليد أنواع typescript من الكود المصدري ويعرضها عبر حزمة npm.
الترحيل: أزل @types/webpack. قم بتحديث المراجع (references) عندما تختلف الأسماء.
تغييرات رئيسية: التحسين (Optimization)
اهتزاز الشجرة المتداخل (Nested tree-shaking)
أصبح Webpack الآن قادرًا على تتبع الوصول إلى الخصائص المتداخلة للصادرات. يمكن أن يؤدي ذلك إلى تحسين Tree Shaking (إزالة الصادرات غير المستخدمة وتغيير أسماء الصادرات) عند إعادة تصدير كائنات مساحات الأسماء (namespace objects).
inner.js
export const a = 1;
export const b = 2;module.js
export * as inner from "./inner";
// أو import * as inner from './inner'; export { inner };user.js
import * as module from "./module";
console.log(module.inner.a);في هذا المثال، يمكن إزالة التصدير b في وضع الإنتاج.
اهتزاز الشجرة للوحدة الداخلية (Inner-module tree-shaking)
لم يقم Webpack 4 بتحليل التبعيات بين صادرات واستيرادات الوحدة. يمتلك Webpack 5 خيارًا جديدًا optimization.innerGraph، وهو مفعل افتراضيًا في وضع الإنتاج، والذي يُجري تحليلاً على الرموز في وحدة لمعرفة التبعيات من الصادرات إلى الاستيرادات.
في وحدة مثل هذه:
import { something } from "./something";
function usingSomething() {
return something;
}
export function test() {
return usingSomething();
}سيكتشف خوارزمية الرسم البياني الداخلي (inner graph) أن something يُستخدم فقط عند استخدام التصدير test. يتيح هذا وضع علامة على المزيد من الصادرات على أنها غير مستخدمة وحذف المزيد من التعليمات البرمجية من الحزمة.
عند ضبط "sideEffects": false، يسمح هذا بحذف المزيد من الوحدات. في هذا المثال سيتم حذف ./something عندما يكون التصدير test غير مستخدم.
للحصول على معلومات حول الصادرات غير المستخدمة، يلزم وجود optimization.usedExports. ولإزالة الوحدات الخالية من الآثار الجانبية، يلزم وجود optimization.sideEffects.
يمكن تحليل الرموز التالية:
- تصريحات الدوال (function declarations)
- تصريحات الفئات (class declarations)
export defaultمع المتغيرات أو تصريحات المتغيرات مع:- تعبيرات الدوال (function expressions)
- تعبيرات الفئات (class expressions)
- التعبيرات المتسلسلة (sequence expressions)
- تعبيرات
/*#__PURE__*/ - المتغيرات المحلية (local variables)
- الروابط المستوردة (imported bindings)
ملاحظاتك (FEEDBACK): إذا وجدت شيئًا مفقودًا في هذا التحليل، يرجى الإبلاغ عن مشكلة وسننظر في إضافتها.
سيؤدي استخدام eval() إلى الخروج من هذا التحسين للوحدة، لأن الكود الذي يتم تقييمه (evaled code) يمكن أن يشير إلى أي رمز في النطاق (scope).
يُعرف هذا التحسين أيضًا باسم Deep Scope Analysis (تحليل النطاق العميق).
اهتزاز شجرة CommonJs (CommonJs Tree Shaking)
كان Webpack ينسحب من تحليل الصادرات المستخدمة لصادرات CommonJs واستدعاءات require().
يضيف Webpack 5 دعمًا لبعض هياكل CommonJs، ويسمح بالتخلص من صادرات CommonJs غير المستخدمة وتتبع أسماء التصدير المشار إليها من استدعاءات require().
الهياكل التالية مدعومة:
exports|this|module.exports.xxx = ...exports|this|module.exports = require("...")(إعادة تصدير)exports|this|module.exports.xxx = require("...").xxx(إعادة تصدير)Object.defineProperty(exports|this|module.exports, "xxx", ...)require("abc").xxxrequire("abc").xxx()- الاستيراد من ESM
require()لـ ESM- flagged exportType (معالجة خاصة لاستيراد ESM غير الصارم):
Object.defineProperty(exports|this|module.exports, "__esModule", { value: true|!0 })exports|this|module.exports.__esModule = true|!0
- من المخطط دعم المزيد من الهياكل في المستقبل
عند اكتشاف كود غير قابل للتحليل، ينسحب webpack ولا يتتبع معلومات التصدير على الإطلاق لهذه الوحدات (لأسباب تتعلق بالأداء).
تحليل الآثار الجانبية (Side-Effect analysis)
تسمح علامة "sideEffects" في package.json بوضع علامة يدويًا على الوحدات بأنها خالية من الآثار الجانبية، مما يسمح بحذفها عند عدم استخدامها.
يمكن لـ Webpack 5 أيضًا وضع علامة تلقائيًا على الوحدات كخالية من الآثار الجانبية وفقًا للتحليل الثابت للكود المصدري.
التحسين لكل وقت تشغيل (Optimization per runtime)
أصبح Webpack 5 الآن قادرًا (ويفعل ذلك افتراضيًا) على تحليل وتحسين الوحدات لكل وقت تشغيل (غالبًا ما يكون وقت التشغيل مساويًا لنقطة الدخول entrypoint). هذا يسمح بتصديرها فقط في نقاط الدخول هذه حيث تكون هناك حاجة فعلية إليها. لا تؤثر نقاط الدخول على بعضها البعض (طالما تم استخدام وقت تشغيل لكل نقطة دخول).
تسلسل الوحدات (Module Concatenation)
يعمل تسلسل الوحدات أيضًا لكل وقت تشغيل للسماح بتسلسل مختلف لكل وقت تشغيل.
أصبح تسلسل الوحدات مواطنًا من الدرجة الأولى ويُسمح الآن لأي وحدة وتابعية (dependency) بتنفيذه. مبدئيًا أضاف webpack 5 بالفعل دعمًا للوحدات الخارجية (ExternalModules) ووحدات json، ومن المحتمل أن يتم شحن المزيد قريبًا.
تحسينات Tree Shaking العامة (General Tree Shaking improvements)
تم تحسين export * لتتبع المزيد من المعلومات ولم يعد يضع علامة على التصدير default كمستخدم.
سيُظهر export * الآن تحذيرات عندما يتأكد webpack من وجود صادرات متعارضة.
تسمح import() باهتزاز الشجرة للوحدة يدويًا عبر التعليق السحري /* webpackExports: ["abc", "default"] */.
التشابه بين التطوير والإنتاج (Development Production Similarity)
نحاول إيجاد توازن جيد بين أداء البناء في وضع التطوير وتجنب المشاكل الخاصة بالإنتاج فقط عن طريق تحسين التشابه بين كلا الوضعين.
يُفعل Webpack 5 تحسين sideEffects افتراضيًا في كلا الوضعين. في webpack 4، أدى هذا التحسين إلى بعض الأخطاء الخاصة بالإنتاج فقط بسبب علامة "sideEffects" غير صحيحة في package.json. يتيح تفعيل هذا التحسين في التطوير العثور على هذه المشاكل بشكل أسرع وأسهل.
في كثير من الحالات، يحدث التطوير والإنتاج على أنظمة تشغيل مختلفة مع حساسية مختلفة لحالة الأحرف (case-sensitivity) في نظام الملفات، لذا يضيف webpack 5 المزيد من التحذيرات/الأخطاء عندما يكون هناك شيء غريب فيما يتعلق بحالة الأحرف.
توليد الكود المحسن (Improved Code Generation)
يكتشف Webpack متى يحدث الإدراج التلقائي للفواصل المنقوطة (ASI) ويولد كودًا أقصر عند عدم إدراج فواصل منقوطة. Object(...) -> (0, ...)
يدمج Webpack وظائف الحصول على الصادرات (export getters) المتعددة في استدعاء وظيفة وقت تشغيل واحدة: r.d(x, "a", () => a); r.d(x, "b", () => b); -> r.d(x, {a: () => a, b: () => b});
هناك خيارات إضافية في output.environment الآن.
تسمح بتحديد ميزة ECMAScript التي يمكن استخدامها لرمز وقت التشغيل المُنشأ بواسطة webpack.
عادة لا يحدد المرء هذا الخيار مباشرة، ولكنه يستخدم خيار target بدلاً من ذلك.
كان Webpack 4 يصدر كود ES5 فقط. يمكن لـ Webpack 5 الآن توليد كل من كود ES5 و ES6/ES2015.
سيؤدي دعم المتصفحات الحديثة فقط إلى إنشاء رمز أقصر باستخدام الدوال السهمية (arrow functions) وكود أكثر توافقًا مع المواصفات باستخدام تصريحات const مع TDZ لـ export default.
خيار target المحسن
في webpack 4 كان target خيارًا تقريبيًا بين "web" و "node" (وبضعة خيارات أخرى).
يمنحك Webpack 5 المزيد من الخيارات هنا.
يؤثر خيار target الآن على أشياء أكثر حول الكود المُنشأ عما سبق:
- طريقة تحميل الحزمة
- تنسيق الحزم
- طريقة تحميل wasm
- طريقة تحميل الحزمة و wasm في العمال (workers)
- الكائن العام (global object) المستخدم
- ما إذا كان يجب تحديد publicPath تلقائيًا
- ميزات/بناء جملة ECMAScript المستخدمة في الكود المُنشأ
externalsمُمَكّنة بشكل افتراضي- سلوك بعض طبقات التوافق (compat layers) الخاصة بـ Node.js مثل (
global،__filename،__dirname) - تحليل الوحدات (حقل
browser، وشروطexportsوimports) - قد تغير بعض المحملات (loaders) سلوكها بناءً على ذلك
بالنسبة لبعض هذه الأشياء، يكون الاختيار بين "web" و "node" تقريبيًا للغاية ونحتاج إلى مزيد من المعلومات.
لذلك نسمح بتحديد الحد الأدنى للإصدار مثل "node10.13" واستنتاج المزيد من الخصائص حول بيئة الهدف.
يُسمح الآن أيضًا بدمج عدة أهداف مع مصفوفة وسيقوم webpack بتحديد الحد الأدنى من خصائص جميع الأهداف. استخدام مصفوفة مفيد أيضًا عند استخدام أهداف لا تعطي معلومات كاملة مثل "web" أو "node" (بدون رقم إصدار). على سبيل المثال ["web", "es2020"] يجمع بين هذين الهدفين الجزئيين.
هناك هدف "browserslist" والذي سيستخدم بيانات browserslist لتحديد خصائص البيئة.
يُستخدم هذا الهدف أيضًا بشكل افتراضي عندما يكون هناك تكوين browserslist متاح في المشروع. في حالة عدم توفر مثل هذا التكوين، سيتم استخدام هدف "web" بشكل افتراضي.
لم يتم تنفيذ بعض المجموعات والميزات بعد وستؤدي إلى أخطاء. إنها تحضيرات لميزات مستقبلية. أمثلة:
["web", "node"]سيؤدي إلى طريقة تحميل حزمة عالمية (universal chunk loading method)، والتي لم يتم تنفيذها بعد["web", "node"]+output.module: trueسيؤدي إلى طريقة تحميل حزمة وحدة (module chunk loading method)، والتي لم يتم تنفيذها بعد"web"سيؤدي إلى معاملة استيراداتhttp(s):كعناصر خارجية (externals) من النوعmodule، والتي لم يتم تنفيذها بعد (حل بديل:externalsPresets: { web: false, webAsync: true }، والذي سيستخدمimport()بدلاً من ذلك).
تقسيم الحزم وأحجام الوحدات (SplitChunks and Module Sizes)
تُعبّر الوحدات الآن عن الحجم بطريقة أفضل من رقم واحد. هناك أنواع مختلفة من الأحجام الآن.
يعرف SplitChunksPlugin الآن كيفية التعامل مع هذه الأحجام المختلفة ويستخدمها لـ minSize و maxSize.
بشكل افتراضي، يتم التعامل مع حجم javascript فقط، ولكن يمكنك الآن تمرير قيم متعددة لإدارتها:
module.exports = {
optimization: {
splitChunks: {
minSize: {
javascript: 30000,
webassembly: 50000,
},
},
},
};لا يزال بإمكانك استخدام رقم واحد للأحجام. في هذه الحالة، سيستخدم webpack أنواع الأحجام الافتراضية تلقائيًا.
يستخدم mini-css-extract-plugin نوع الحجم css/mini-extra، ويضيف نوع الحجم هذا إلى الأنواع الافتراضية تلقائيًا.
تغييرات رئيسية: الأداء (Performance)
التخزين المؤقت المستمر (Persistent Caching)
يوجد الآن نظام تخزين مؤقت على نظام الملفات (filesystem cache). يتطلب الاشتراك (opt-in) ويمكن تفعيله باستخدام التكوين التالي:
module.exports = {
cache: {
// 1. Set cache type to filesystem
type: "filesystem",
buildDependencies: {
// 2. Add your config as buildDependency to get cache invalidation on config change
config: [__filename],
// 3. If you have other things the build depends on you can add them here
// Note that webpack, loaders and all modules referenced from your config are automatically added
},
},
};ملاحظات هامة:
افتراضيًا، يفترض webpack أن مجلد node_modules، الذي يتواجد بداخله webpack، يتم تعديله فقط بواسطة مدير الحزم (package manager). يتم تخطي حساب التجزئة (Hashing) والطابع الزمني (timestamping) لمجلد node_modules.
بدلاً من ذلك، يتم استخدام اسم الحزمة وإصدارها فقط لأسباب تتعلق بالأداء.
الروابط الرمزية (Symlinks) (أي npm/yarn link) لا بأس بها طالما لم يتم تحديد resolve.symlinks: false (تجنب ذلك على أي حال).
لا تقم بتعديل الملفات في node_modules مباشرة إلا إذا انسحبت (opt-out) من هذا التحسين باستخدام snapshot.managedPaths: [].
عند استخدام Yarn PnP، يفترض webpack أن التخزين المؤقت لـ yarn غير قابل للتغيير (وهو ما يكون عليه عادةً).
يمكنك الانسحاب من هذا التحسين باستخدام snapshot.immutablePaths: []
سيتم حفظ ذاكرة التخزين المؤقت في node_modules/.cache/webpack (عند استخدام node_modules) أو في .yarn/.cache/webpack (عند استخدام Yarn PnP) بشكل افتراضي.
من المحتمل أنك لن تضطر أبدًا إلى حذفه يدويًا، عندما تتعامل جميع الإضافات مع التخزين المؤقت بشكل صحيح.
العديد من الإضافات الداخلية ستستخدم "التخزين المؤقت المستمر" أيضًا. أمثلة: SourceMapDevToolPlugin (لتخزين توليد خريطة المصدر مؤقتًا) أو ProgressPlugin (لتخزين عدد الوحدات مؤقتًا)
سيقوم التخزين المؤقت المستمر تلقائيًا بإنشاء ملفات ذاكرة تخزين مؤقت متعددة اعتمادًا على الاستخدام لتحسين الوصول للقراءة والكتابة من وإلى ذاكرة التخزين المؤقت.
بشكل افتراضي، سيتم استخدام الطوابع الزمنية (timestamps) لأخذ اللقطات (snapshotting) في وضع التطوير (development mode) وتجزئة الملفات (file hashes) في وضع الإنتاج. تسمح تجزئة الملفات باستخدام التخزين المؤقت المستمر في عمليات التكامل المستمر (CI) أيضًا.
خمول المترجم وإغلاقه (Compiler Idle and Close)
تحتاج المترجمات (Compilers) الآن إلى الإغلاق بعد استخدامها. المترجمات تدخل الآن وتترك حالة الخمول (idle state) ولها خطافات (hooks) لهذه الحالات. قد تستخدم الإضافات هذه الخطافات للقيام بأعمال غير مهمة. (أي أن التخزين المؤقت المستمر يقوم ببطء بتخزين ذاكرة التخزين المؤقت على القرص). عند إغلاق المترجم - يجب الانتهاء من جميع الأعمال المتبقية في أسرع وقت ممكن. تشير دالة استدعاء (callback) إلى الانتهاء من الإغلاق.
يجب أن تتوقع الإضافات ومؤلفوها أن بعض المستخدمين قد ينسون إغلاق المترجم. لذلك، يجب أن تنتهي كل الأعمال في النهاية أثناء الخمول أيضًا. يجب منع العمليات من الخروج عند إنجاز العمل.
تستدعي واجهة webpack() تلقائيًا close عند تمرير دالة استدعاء.
الترحيل: أثناء استخدام Node.js API، تأكد من استدعاء Compiler.close عند الانتهاء.
إصدار الملف (File Emitting)
كان Webpack يقوم دائمًا بإصدار جميع ملفات الإخراج أثناء البناء الأول ولكنه يتخطى كتابة الملفات غير المتغيرة أثناء عمليات البناء المتزايدة (بناء المراقب - watch builds). يُفترض أنه لا يوجد شيء آخر يغير ملفات المخرجات أثناء تشغيل webpack.
مع إضافة "التخزين المؤقت المستمر"، يجب إعطاء تجربة تشبه المراقبة (watch-like) حتى عند إعادة تشغيل عملية webpack، ولكن سيكون من الافتراض القوي جدًا الاعتقاد بأنه لا يوجد شيء آخر يغير دليل المخرجات حتى عندما لا يكون webpack قيد التشغيل.
لذا سيقوم webpack الآن بفحص الملفات الموجودة في دليل المخرجات ويقارن محتواها مع ملف المخرجات في الذاكرة. سيقوم بكتابة الملف فقط عندما يكون قد تم تغييره. يتم ذلك فقط في البناء الأول. ستقوم أي عملية بناء متزايدة دائمًا بكتابة الملف عند إنشاء أصل جديد في عملية webpack قيد التشغيل.
نحن نفترض أن webpack والإضافات تقوم فقط بإنشاء أصول جديدة عند تغيير المحتوى. يجب استخدام التخزين المؤقت للتأكد من عدم إنشاء أصل جديد عندما تكون المدخلات متساوية. عدم اتباع هذه النصيحة سيؤدي إلى انخفاض الأداء.
الملفات التي تم تمييزها بعلامة [immutable] (بما في ذلك تجزئة المحتوى)، لن يتم كتابتها أبدًا عند وجود ملف بنفس الاسم بالفعل.
نفترض أن تجزئة المحتوى ستتغير عندما يتغير محتوى الملف.
هذا صحيح بشكل عام، ولكنه قد لا يكون صحيحًا دائمًا أثناء تطوير webpack أو الإضافة.
تغييرات رئيسية: مشاكل بارزة منذ فترة طويلة (Long outstanding problems)
تقسيم الكود لأهداف الملف الواحد (Code Splitting for single-file-targets)
الأهداف التي تسمح فقط ببدء تشغيل ملف واحد (مثل node، و WebWorker، و electron main) تدعم الآن تحميل الأجزاء التابعة المطلوبة لعملية التهيئة (bootstrapping) تلقائيًا بواسطة وقت التشغيل (runtime).
يسمح هذا باستخدام optimization.splitChunks لهذه الأهداف باستخدام chunks: "all" وأيضًا optimization.runtimeChunk.
لاحظ أنه مع الأهداف التي يكون فيها تحميل الحزمة غير متزامن، يجعل هذا التقييم الأولي (initial evaluation) غير متزامن أيضًا. يمكن أن يمثل هذا مشكلة عند استخدام output.library، حيث أن القيمة المُصدّرة هي Promise الآن.
المحلل المحدث (Updated Resolver)
تم تحديث enhanced-resolve إلى v5. هذا يحتوي على التحسينات التالية:
- يتتبع المحلل المزيد من التبعيات، مثل الملفات المفقودة
- قد يكون للأسماء المستعارة (aliasing) بدائل متعددة
- يمكن الآن استخدام الأسماء المستعارة إلى
false - دعم ميزات مثل حقول
exportsوimports - زيادة الأداء
حزم بدون JS
الحزم التي لا تحتوي على كود JS، لن تُولد بعد الآن ملف JS. يسمح هذا بالحصول على حزم تحتوي على CSS فقط.
تغييرات رئيسية: المستقبل (Future)
تجارب (Experiments)
ليست كل الميزات مستقرة منذ البداية. في webpack 4 أضفنا ميزات تجريبية وأشرنا في سجل التغيير (changelog) إلى أنها تجريبية، ولكن لم يكن من الواضح دائمًا من التكوين أن هذه الميزات تجريبية.
في webpack 5، يوجد خيار تكوين جديد experiments يسمح بتمكين الميزات التجريبية. هذا يوضح ماهية الميزات التي يتم تمكينها/استخدامها.
في حين يتبع webpack نظام تحديد الإصدارات الدلالي (semantic versioning)، فإنه سيستثني الميزات التجريبية. قد تحتوي الميزات التجريبية على تغييرات جذرية في إصدارات webpack الثانوية. عندما يحدث هذا سنضيف ملاحظة واضحة إلى سجل التغيير. سيتيح لنا هذا تكرار الميزات التجريبية بشكل أسرع، مع السماح لنا أيضًا بالبقاء لفترة أطول في إصدار رئيسي للميزات المستقرة.
سيتم شحن التجارب التالية مع webpack 5:
- دعم WebAssembly القديم مثلما في webpack 4 (
experiments.syncWebAssembly) - دعم WebAssembly الجديد وفقًا لـ المواصفة المحدثة (
experiments.asyncWebAssembly)- هذا يجعل وحدة WebAssembly وحدة غير متزامنة (async module)
- اقتراح المرحلة 3 من الانتظار في المستوى الأعلى (Top Level Await) (
experiments.topLevelAwait)- استخدام
awaitفي المستوى الأعلى يجعل الوحدة وحدة غير متزامنة
- استخدام
- إصدار الحزمة كوحدة (
experiments.outputModule)- هذا يزيل التغليف IIFE من الحزمة، ويفرض وضع strict، ويقوم بالتحميل البطيء (lazy loads) عبر
<script type="module">وتصغيره في وضع الوحدة
- هذا يزيل التغليف IIFE من الحزمة، ويفرض وضع strict، ويقوم بالتحميل البطيء (lazy loads) عبر
لاحظ أن هذا يعني أيضًا أن دعم WebAssembly معطل الآن بشكل افتراضي.
الحد الأدنى لإصدار Node.js
تمت زيادة الحد الأدنى لإصدار Node.js المدعوم من 6 إلى 10.13.0(LTS).
الترحيل: الترقية إلى أحدث إصدار متاح من Node.js.
تغييرات على التكوين (Configuration)
تغييرات على الهيكل (Structure)
entry: {}يسمح بكائن فارغ الآن (للسماح باستخدام الإضافات لإضافة إدخالات)- يدعم
targetمصفوفة (array) وإصدارات و browserslist - إزالة
cache: Object: لم يعد الإعداد إلى كائن ذاكرة تخزين مؤقت في الذاكرة ممكنًا - إضافة
cache.type: أصبح من الممكن الآن الاختيار بين"memory"و"filesystem" - إضافة خيارات تكوين جديدة لـ
cache.type = "filesystem":cache.cacheDirectorycache.namecache.versioncache.storecache.hashAlgorithmcache.idleTimeoutcache.idleTimeoutForInitialStorecache.buildDependencies
- إضافة
snapshot.resolveBuildDependencies - إضافة
snapshot.resolve - إضافة
snapshot.module - إضافة
snapshot.managedPaths - إضافة
snapshot.immutablePaths - إضافة
resolve.cache: يسمح بتعطيل/تفعيل ذاكرة التخزين المؤقت الآمنة للتحليل (resolve cache) - إزالة
resolve.concord - إزالة
resolve.moduleExtensions - يمكن أن تكون قيم
resolve.aliasالآن مصفوفات (arrays) أوfalse - إضافة
resolve.restrictions: يسمح بتقييد نتائج التحليل المحتملة - إضافة
resolve.fallback: السماح بإنشاء اسم مستعار للطلبات التي فشل تحليلها - إضافة
resolve.preferRelative: السماح بتحليل طلبات الوحدات كطلبات نسبية أيضًا - تمت إزالة التعويضات (polyfills) التلقائية لوحدات Node.js المحلية
- إزالة
node.Buffer - إزالة
node.console - إزالة
node.process - إزالة
node.*(وحدات Node.js المحلية) - الترحيل:
resolve.aliasوProvidePlugin. ستعطي الأخطاء تلميحات. (راجع node-libs-browser للتعويضات والبدائل (mocks) المستخدمة في الإصدار 4)
- إزالة
- يمكن أن يكون
output.filenameالآن دالة (function) - إضافة
output.assetModuleFilename - إعادة تسمية
output.jsonpScriptTypeإلىoutput.scriptType - أصبحت
devtoolأكثر صرامة- التنسيق:
false | eval | [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
- التنسيق:
- إضافة
optimization.chunkIds: "deterministic" - إضافة
optimization.moduleIds: "deterministic" - تم إهمال
optimization.moduleIds: "hashed" - إزالة
optimization.moduleIds: "total-size" - تمت إزالة العلامات المهملة (Deprecated flags) لمعرفات الوحدات والحزم
- إزالة
optimization.hashedModuleIds - إزالة
optimization.namedChunks(وكذلكNamedChunksPlugin) - إزالة
optimization.namedModules(وكذلكNamedModulesPlugin) - إزالة
optimization.occurrenceOrder - الترحيل: استخدم
chunkIdsوmoduleIds
- إزالة
- لم تعد مطابقة (test) لـ
optimization.splitChunksتتطابق مع اسم الحزمة- الترحيل: استخدم دالة مطابقة (test function)
(module, { chunkGraph }) => chunkGraph.getModuleChunks(module).some(chunk => chunk.name === "name")
- الترحيل: استخدم دالة مطابقة (test function)
- إضافة
optimization.splitChunksminRemainingSize - يمكن أن يكون
optimization.splitChunksfilenameالآن دالة (function) - يمكن أن تكون أحجام
optimization.splitChunksالآن كائنات مع حجم لكل نوع مصدر (source type)minSizeminRemainingSizemaxSizemaxAsyncSizemaxInitialSize
- تمت إضافة
maxAsyncSizeوmaxInitialSizeفيoptimization.splitChunksبجوارmaxSize: يسمح بتحديد أحجام قصوى مختلفة للحزم الأولية وغير المتزامنة - تمت إزالة
name: trueمنoptimization.splitChunks: لم تعد الأسماء التلقائية مدعومة- الترحيل: استخدم الافتراضي. سيعطي
chunkIds: "named"ملفاتك أسماء مفيدة لتصحيح الأخطاء
- الترحيل: استخدم الافتراضي. سيعطي
- إضافة
optimization.splitChunks.cacheGroups[].idHint: يعطي تلميحًا حول كيفية اختيار معرف الحزمة المسماة - تمت إزالة
automaticNamePrefixمنoptimization.splitChunks- الترحيل: استخدم
idHintبدلاً من ذلك
- الترحيل: استخدم
- لم يعد
filenameفيoptimization.splitChunksمقصورًا على الحزم الأولية - إضافة
usedExportsفيoptimization.splitChunksلتضمين الصادرات المستخدمة عند مقارنة الوحدات - إضافة
optimization.splitChunks.defaultSizeTypes: تحدد أنواع الأحجام عند استخدام الأرقام للأحجام - إضافة
optimization.mangleExports - يمكن استخدام
"..."فيoptimization.minimizerللإشارة إلى الافتراضيات - إضافة القيمة
"global"إلىoptimization.usedExportsللسماح بتعطيل التحليل لكل وقت تشغيل والقيام بذلك بشكل عام (أداء أفضل) - إعادة تسمية
optimization.noEmitOnErrorsإلىoptimization.emitOnErrorsوعكس المنطق - إضافة
optimization.realContentHash - إزالة
output.devtoolLineToLine- الترحيل: لا يوجد بديل
- أصبح
output.chunkFilename: Functionمسموحًا به الآن - أصبح
output.hotUpdateChunkFilename: Functionمحظورًا الآن: لم ينجح الأمر أبدًا على أي حال. - أصبح
output.hotUpdateMainFilename: Functionمحظورًا الآن: لم ينجح الأمر أبدًا على أي حال. - تحدد
output.importFunctionName: stringالاسم المستخدم كبديل لـimport()للسماح بالتعويض (polyfilling) للبيئات غير المدعومة - إضافة
output.charset: إعداده إلى false يحذف الخاصيةcharsetمن علامات (tags)script - إعادة تسمية
output.hotUpdateFunctionإلىoutput.hotUpdateGlobal - إعادة تسمية
output.jsonpFunctionإلىoutput.chunkLoadingGlobal - إعادة تسمية
output.chunkCallbackFunctionإلىoutput.chunkLoadingGlobal - إضافة
output.chunkLoading - إضافة
output.enabledChunkLoadingTypes - إضافة
output.chunkFormat - ستندمج (merge)
resolveوparserفيmodule.rulesبطريقة مختلفة (يتم دمج الكائنات (objects) بعمق، وقد تتضمن المصفوفة (array)"..."للإشارة إلى القيمة السابقة) - إضافة
module.rulesparser.worker: يسمح بتكوين الـ worker المدعوم - إزالة
queryوloadersمنmodule.rules - تم إهمال تمرير سلسلة نصية (string) لـ
optionsفيmodule.rules- الترحيل: قم بتمرير كائن خيارات (options object) بدلاً من ذلك، افتح مشكلة على المحمل (loader) عندما لا يكون هذا مدعومًا
- إضافة
module.rulesmimetype: يسمح بمطابقة نوع MIME (mimetype) الخاص بـ DataURI - إضافة
module.rulesdescriptionData: يسمح بمطابقة بيانات من package.json - يمكن استخدام
"..."فيmodule.defaultRulesللإشارة إلى الافتراضيات - إضافة
stats.chunkRootModules: عرض وحدات الجذر (root modules) للحزم - إضافة
stats.orphanModules: إظهار الوحدات التي لا يتم إصدارها - إضافة
stats.runtime: عرض وحدات وقت التشغيل - إضافة
stats.chunkRelations: عرض علاقات الحزم الأم/الأبناء/الإخوة (parent/children/sibling chunks) - إضافة
stats.errorStack: عرض تتبع التكدس الداخلي للأخطاء في webpack (webpack-internal stack trace of errors) - إضافة
stats.preset: تحديد الإعداد المسبق (preset) - إضافة
stats.relatedAssets: إظهار الأصول (assets) المرتبطة بأصول أخرى (مثل SourceMaps) - تم إهمال
stats.warningsFilterلصالحignoreWarnings - تغيير توقيع (signature)
BannerPlugin.banner- إزالة
data.basename - إزالة
data.query - الترحيل: الاستخراج من
filename
- إزالة
- إزالة
lineToLineمنSourceMapDevToolPlugin- الترحيل: لا يوجد بديل
- أصبح استخدام
[hash]كتجزئة للتجميع (compilation) بالكامل مهملًا الآن- الترحيل: استخدم
[fullhash]بدلاً من ذلك، أو من الأفضل استخدام خيار تجزئة آخر
- الترحيل: استخدم
- إهمال
[modulehash]- الترحيل: استخدم
[hash]بدلاً من ذلك
- الترحيل: استخدم
- إهمال
[moduleid]- الترحيل: استخدم
[id]بدلاً من ذلك
- الترحيل: استخدم
- إزالة
[filebase]- الترحيل: استخدم
[base]بدلاً من ذلك
- الترحيل: استخدم
- عناصر نائبة (placeholders) جديدة للقوالب القائمة على الملفات (أي SourceMapDevToolPlugin)
[name][base][path][ext]
externalsعند تمرير دالة (function)، أصبح لها الآن توقيع مختلف({ context, request }, callback)- الترحيل: تغيير التوقيع
- إضافة
externalsPresets - إضافة
experiments(راجع قسم التجارب - Experiments أعلاه) - إضافة
watchOptions.followSymlinks - يمكن أن يكون
watchOptions.ignoredالآن تعبيرًا نمطيًا (RegExp) - تم الآن عرض (exposed)
webpack.util.serialization.
التغييرات على الافتراضيات (Changes to the Defaults)
- أصبح
targetالآن"browserslist"افتراضيًا عندما يكون تكوين browserslist متاحًا - يتم الآن تفعيل
module.unsafeCacheفقط لـnode_modulesبشكل افتراضي - يتم افتراضيًا ضبط
optimization.moduleIdsعلىdeterministicفي وضع الإنتاج، بدلاً منsize - يتم افتراضيًا ضبط
optimization.chunkIdsعلىdeterministicفي وضع الإنتاج، بدلاً منtotal-size - يتم افتراضيًا ضبط
optimization.nodeEnvعلىfalseفي وضعnone - يتم افتراضيًا ضبط
optimization.splitChunks.minSizeعلى20kفي الإنتاج - يتم افتراضيًا ضبط
optimization.splitChunks.enforceSizeThresholdعلى50kفي الإنتاج - يتم افتراضيًا ضبط
optimization.splitChunksminRemainingSizeعلىminSize- سيؤدي هذا إلى إنشاء حزم مقسمة (splitted chunks) أقل في الحالات التي يكون فيها الجزء المتبقي صغيرًا جدًا
- تمت زيادة القيمة الافتراضية لكل من
maxAsyncRequestsوmaxInitialRequestsفيoptimization.splitChunksإلى 30 - تمت إعادة تسمية
optimization.splitChunks.cacheGroups.vendorsإلىoptimization.splitChunks.cacheGroups.defaultVendors - يُعيّن
optimization.splitChunks.cacheGroups.defaultVendors.reuseExistingChunkافتراضيًا الآن إلىtrue - يستخدم الإعداد الافتراضي لهدف
optimization.minimizerالآنcompress.passes: 2في خيارات terser - يعيّن
resolve(Loader).cacheافتراضيًا إلىtrueعند استخدامcache - يعيّن
resolve(Loader).cacheWithContextافتراضيًا إلىfalse - إزالة
.jsonمنresolveLoader.extensions - يتم افتراضيًا ضبط
node.global،node.__filenameوnode.__dirnameعلىfalseفي أهداف node (node-targets) - يتم افتراضيًا ضبط
stats.errorStackعلىfalse
التغييرات المتعلقة بالمحمل (Loader related Changes)
this.getOptions
يجب أن تعمل واجهة برمجة التطبيقات (API) الجديدة هذه على تبسيط استخدام الخيارات في المحملات. يسمح بتمرير مخطط JSON (JSON schema) للتحقق من الصحة. راجع PR للتفاصيل.
this.exec
تمت إزالة هذا من سياق المحمل (loader context)
الترحيل: يمكن تنفيذ هذا في المحمل نفسه
this.getResolve
ستقوم getResolve(options) في واجهة المحمل بدمج الخيارات بطريقة مختلفة، راجع resolve في module.rules.
حيث يختلف webpack 5 بين تبعيات الإصدار المختلفة، لذلك قد يكون من المنطقي تمرير dependencyType كخيار (مثل "esm"، "commonjs"، أو غيرها).
تغييرات داخلية رئيسية (Major Internal Changes)
التغييرات التالية ذات صلة فقط لمؤلفي الإضافات (plugin authors):
ترتيب الإضافات الجديد (New plugin order)
يتم الآن تطبيق الإضافات في webpack 5 قبل تطبيق الافتراضيات الخاصة بالتكوين. يسمح هذا للإضافات بتطبيق الافتراضيات الخاصة بها، أو العمل كإعدادات مسبقة للتكوين (configuration presets).
ولكن هذا يمثل أيضًا تغييرًا جذريًا لأن الإضافات لا يمكنها الاعتماد على قيم التكوين التي يتم تعيينها عند تطبيقها.
الترحيل: يمكنك الوصول إلى التكوين فقط في خطافات (hooks) الإضافات. أو من الأفضل تجنب الوصول إلى التكوين على الإطلاق وأخذ الخيارات عبر المُنشئ (constructor).
وحدات وقت التشغيل (Runtime Modules)
تم نقل جزء كبير من كود وقت التشغيل إلى ما يسمى بـ "وحدات وقت التشغيل". هذه الوحدات الخاصة مسؤولة عن إضافة كود وقت التشغيل. يمكن إضافتها إلى أي حزمة، ولكنها حاليًا تُضاف دائمًا إلى حزمة وقت التشغيل (runtime chunk). تتحكم "متطلبات وقت التشغيل (Runtime Requirements)" في وحدات وقت التشغيل (أو أجزاء وقت التشغيل الأساسية) التي تُضاف إلى الحزمة. يضمن هذا إضافة كود وقت التشغيل المستخدم فقط إلى الحزمة. في المستقبل، يمكن أيضًا إضافة وحدات وقت التشغيل إلى حزمة يتم تحميلها عند الطلب، لتحميل كود وقت التشغيل عند الحاجة.
في معظم الحالات، يسمح وقت التشغيل الأساسي (core runtime) بتضمين وحدة الدخول (inlining the entry module) بدلاً من استدعائها باستخدام __webpack_require__. إذا لم تكن هناك وحدة أخرى في الحزمة، فلن تكون هناك حاجة إلى __webpack_require__ على الإطلاق. يتحد هذا بشكل جيد مع تسلسل الوحدات (Module Concatenation) حيث يتم ربط وحدات متعددة في وحدة واحدة.
في أفضل الحالات، لن تكون هناك حاجة إلى كود وقت التشغيل على الإطلاق.
الترحيل: إذا كنت تقوم بحقن كود وقت التشغيل في وقت تشغيل webpack داخل إضافة (plugin)، ففكر في استخدام وحدات وقت التشغيل (RuntimeModules) بدلاً من ذلك.
التسلسل (Serialization)
تمت إضافة آلية تسلسل للسماح بتسلسل الكائنات المعقدة في webpack. يحتوي على دلالات اختيارية (opt-in)، لذلك يجب وضع علامة واضحة على الفئات التي يجب أن تكون متسلسلة (وتنفيذ التسلسل الخاص بها). تم القيام بذلك لمعظم الوحدات (Modules)، وجميع التبعيات (Dependencies) وبعض الأخطاء (Errors).
الترحيل: عند استخدام وحدات أو تبعيات مخصصة، يوصى بجعلها قابلة للتسلسل (serializable) للاستفادة من التخزين المؤقت المستمر.
إضافات للتخزين المؤقت (Plugins for Caching)
تمت إضافة فئة Cache مع واجهة إضافة. يمكن استخدام هذه الفئة للكتابة والقراءة من ذاكرة التخزين المؤقت. اعتمادًا على التكوين، يمكن للإضافات المختلفة إضافة وظائف إلى التخزين المؤقت. تضيف إضافة MemoryCachePlugin التخزين المؤقت داخل الذاكرة (in-memory). تضيف إضافة FileCachePlugin التخزين المؤقت المستمر (Persistent) (على نظام الملفات).
يستخدم FileCachePlugin آلية التسلسل للحفاظ على العناصر المخزنة مؤقتًا واستعادتها من/إلى القرص.
تجميد كائن الخطاف (Hook Object Frozen)
تم تجميد (frozen) كائن hooks للفئات (Classes) التي تحتوي على hooks، لذا لم يعد من الممكن إضافة خطافات مخصصة (custom hooks) بهذه الطريقة.
الترحيل: الطريقة الموصى بها لإضافة خطافات مخصصة هي استخدام WeakMap وطريقة ثابتة getXXXHooks(XXX) (أي getCompilationHook(compilation)). تستخدم الفئات الداخلية نفس الآلية المستخدمة للخطافات المخصصة.
ترقية Tapable (Tapable Upgrade)
تمت إزالة طبقة التوافق (compat layer) لإضافات webpack 3. وقد تم إهمالها بالفعل في webpack 4.
تمت إزالة أو إهمال بعض واجهات برمجة تطبيقات (APIs) tapable الأقل استخدامًا.
الترحيل: استخدم واجهة برمجة تطبيقات tapable الجديدة.
الخطافات المرحلية (Staged Hooks)
بالنسبة لعدة خطوات في عملية الختم (sealing process)، كانت هناك خطافات متعددة لمراحل مختلفة. مثل optimizeDependenciesBasic و optimizeDependencies و optimizeDependenciesAdvanced. تمت إزالتها لصالح خطاف واحد يمكن استخدامه مع خيار stage. راجع OptimizationStages لقيم المرحلة الممكنة.
الترحيل: اربط (Hook into) بالخطاف المتبقي بدلاً من ذلك. يمكنك إضافة خيار stage.
إهمال Main/Chunk/ModuleTemplate
تمت إعادة هيكلة قوالب الحزم (Bundle templating). تم إهمال MainTemplate/ChunkTemplate/ModuleTemplate وتتولى JavascriptModulesPlugin مسؤولية قوالب JS الآن.
قبل إعادة الهيكلة هذه، كان يتم التعامل مع مخرجات JS بواسطة Main/ChunkTemplate بينما كان يتم التعامل مع المخرجات الأخرى (مثل WASM، CSS) بواسطة الإضافات. يبدو هذا وكأن JS من الدرجة الأولى، بينما المخرجات الأخرى من الدرجة الثانية. أدت إعادة الهيكلة إلى تغيير ذلك ويتم التعامل مع جميع المخرجات بواسطة إضافاتها الخاصة.
لا يزال من الممكن الربط (hook into) بأجزاء من القوالب. الخطافات موجودة في JavascriptModulesPlugin بدلاً من Main/ChunkTemplate الآن. (نعم يمكن أن تحتوي الإضافات على خطافات أيضًا. أسميها الخطافات المرفقة - attached hooks).
توجد طبقة توافق (compat-layer)، لذا لا يزال Main/Chunk/ModuleTemplate موجودين، لكنهم يقومون فقط بتفويض (delegate) استدعاءات tap إلى مواقع الخطافات الجديدة.
الترحيل: اتبع النصائح الموجودة في رسائل الإهمال. وهي في الغالب تشير إلى الخطافات في مواقع مختلفة.
واصف نقطة الدخول (Entry point descriptor)
إذا تم تمرير كائن (object) كنقطة دخول، فقد تكون القيمة سلسلة نصية (string)، أو مصفوفة من السلاسل النصية (array of strings)، أو واصفًا (descriptor):
module.exports = {
entry: {
catalog: {
import: "./catalog.js",
},
},
};يمكن استخدام بناء جملة الواصف (Descriptor syntax) لتمرير خيارات إضافية إلى نقطة الدخول.
اسم ملف المخرجات لنقطة الدخول (Entry point output filename)
بشكل افتراضي، يتم استخراج اسم ملف الإخراج للحزمة الأولية (entry chunk) من output.filename ولكن يمكنك تحديد اسم ملف إخراج مخصص لإدخال (entry) معين:
module.exports = {
entry: {
about: { import: "./about.js", filename: "pages/[name][ext]" },
},
};تبعية نقطة الدخول (Entry point dependency)
افتراضيًا، تخزن كل حزمة أولية (entry chunk) جميع الوحدات التي تستخدمها. باستخدام خيار dependOn يمكنك مشاركة الوحدات من حزمة أولية إلى أخرى:
module.exports = {
entry: {
app: { import: "./app.js", dependOn: "react-vendors" },
"react-vendors": ["react", "react-dom", "prop-types"],
},
};لن تحتوي حزمة app على الوحدات الموجودة في react-vendors.
مكتبة نقطة الدخول (Entry point library)
يسمح واصف الإدخال (entry descriptor) بتمرير خيار library مختلف لكل نقطة دخول.
module.exports = {
entry: {
commonjs: {
import: "./lib.js",
library: {
type: "commonjs-module",
},
},
amd: {
import: "./lib.js",
library: {
type: "amd",
},
},
},
};وقت تشغيل نقطة الدخول (Entry point runtime)
يسمح واصف الإدخال بتحديد runtime لكل إدخال.
عند تحديده، يتم إنشاء حزمة بهذا الاسم والتي تحتوي فقط على كود وقت التشغيل للإدخال.
عندما تحدد مدخلات متعددة نفس الـ runtime، ستحتوي تلك الحزمة على وقت تشغيل مشترك (common runtime) لجميع هذه المدخلات.
وهذا يعني أنه يمكن استخدامهم معًا في نفس صفحة HTML.
module.exports = {
entry: {
app: {
import: "./app.js",
runtime: "app-runtime",
},
},
};تحميل حزمة نقطة الدخول (Entry point chunk loading)
يسمح واصف الإدخال بتحديد chunkLoading لكل إدخال.
سيستخدم وقت التشغيل لهذا الإدخال هذا الخيار لتحميل الحزم.
module.exports = {
entry: {
app: {
import: "./app.js",
},
worker: {
import: "./worker.js",
chunkLoading: "importScripts",
},
},
};الترتيب والمعرفات (Order and IDs)
كان Webpack يقوم بترتيب الوحدات والحزم في مرحلة التجميع (Compilation phase)، بطريقة معينة، لتعيين المعرفات (IDs) بترتيب تزايدي. لم يعد هذا هو الحال. لن يتم استخدام الترتيب لتوليد المعرف (id) بعد الآن، بدلاً من ذلك، أصبح التحكم الكامل في توليد الـ ID موجودًا في الإضافة (plugin).
تمت إزالة الخطافات (Hooks) المستخدمة لتحسين ترتيب الوحدات والحزم.
الترحيل: لا يمكنك الاعتماد على ترتيب الوحدات والحزم في مرحلة التجميع بعد الآن.
من مصفوفات إلى مجموعات (Arrays to Sets)
- أصبح
Compilation.modulesالآنSet(مجموعة) - أصبح
Compilation.chunksالآنSet - أصبح
Chunk.filesالآنSet
هناك طبقة توافق (compat-layer) تطبع تحذيرات إهمال.
الترحيل: استخدم طرق Set (Set methods) بدلاً من طرق المصفوفة (Array methods).
Compilation.fileSystemInfo
يمكن استخدام هذه الفئة الجديدة للوصول إلى معلومات حول نظام الملفات بطريقة مخزنة مؤقتًا (cached way). تتيح حاليًا طلب طوابع زمنية (timestamps) لكل من الملف والدليل (directory). يتم نقل المعلومات حول الطوابع الزمنية من المراقب (watcher) إن أمكن، وإلا يتم تحديدها عن طريق الوصول إلى نظام الملفات.
في المستقبل، ستتم إضافة السؤال عن تجزئة محتوى الملف (file content hashes) وستتمكن الوحدات من التحقق من الصلاحية (validity) باستخدام محتويات الملف بدلاً من تجزئة الملف.
الترحيل: بدلاً من استخدام file/contextTimestamps استخدم واجهة compilation.fileSystemInfo بدلاً من ذلك.
أصبح وضع الطوابع الزمنية (Timestamping) للأدلة (directories) ممكنًا الآن، مما يسمح بتسلسل (serialization) وحدات ContextModules.
تمت إضافة Compiler.modifiedFiles (بجوار Compiler.removedFiles) لتسهيل الإشارة إلى الملفات المتغيرة.
أنظمة الملفات (Filesystems)
بجوار compiler.inputFileSystem و compiler.outputFileSystem يوجد compiler.intermediateFileSystem جديد لجميع إجراءات نظام الملفات (fs) التي لا تعتبر كإدخال أو إخراج، مثل كتابة السجلات، وذاكرة التخزين المؤقت أو مخرجات التنميط (profiling output).
أنظمة الملفات لديها الآن واجهة fs ولم تعد تتطلب طرقًا إضافية مثل join أو mkdirp. ولكن إذا كان لديهم طرق مثل join أو dirname يتم استخدامها.
الاستبدال الساخن للوحدة (Hot Module Replacement)
تمت إعادة هيكلة وقت تشغيل HMR إلى وحدات وقت تشغيل (Runtime Modules). تم دمج HotUpdateChunkTemplate في ChunkTemplate. يجب أن تتعامل ChunkTemplates والإضافات (plugins) مع HotUpdateChunks الآن أيضًا.
تم فصل جزء javascript من وقت تشغيل HMR عن وقت تشغيل HMR الأساسي. يمكن للأنواع الأخرى من الوحدات الآن التعامل مع HMR بطريقتها الخاصة. في المستقبل، سيسمح هذا بـ HMR لإضافة mini-css-extract-plugin أو لوحدات WASM على سبيل المثال.
الترحيل: نظرًا لأن هذه وظيفة تم تقديمها حديثًا، فلا يوجد شيء لترحيله.
يعرض import.meta.webpackHot نفس واجهة برمجة التطبيقات مثل module.hot. يمكن استخدام هذا أيضًا من وحدات ESM الصارمة (strict ESM modules) (.mjs، النوع type: "module" في package.json) التي ليس لها حق الوصول إلى module.
طوابير العمل (Work Queues)
كان Webpack يتعامل مع معالجة الوحدة عن طريق وظائف (functions) تستدعي وظائف، وإشارة (semaphore) تحد من التوازي (parallelism). تمت إزالة Compilation.semaphore وتقوم الطوابير غير المتزامنة (async queues) الآن بمعالجة طوابير العمل والمعالجة. لكل خطوة طابور منفصل:
Compilation.factorizeQueue: استدعاء مصنع الوحدات (module factory) لمجموعة من التبعيات (dependencies).Compilation.addModuleQueue: إضافة الوحدة إلى طابور التجميع (compilation queue) (قد يستعيد الوحدة من ذاكرة التخزين المؤقت).Compilation.buildQueue: بناء الوحدة إذا لزم الأمر (قد يخزن الوحدة في ذاكرة التخزين المؤقت).Compilation.rebuildQueue: بناء وحدة مرة أخرى إذا تم تشغيلها يدويًا.Compilation.processDependenciesQueue: معالجة التبعيات الخاصة بالوحدة.
تحتوي هذه الطوابير على بعض الخطافات (hooks) لمشاهدة واعتراض معالجة الوظيفة (job processing).
في المستقبل، قد تعمل مترجمات متعددة معًا ويمكن إجراء تنسيق الوظائف (job orchestration) عن طريق اعتراض هذه الطوابير.
الترحيل: نظرًا لأن هذه وظيفة تم تقديمها حديثًا، فلا يوجد شيء لترحيله.
التسجيل (Logging)
تتضمن تصميمات webpack الداخلية بعض التسجيل (logging) الآن.
يمكن استخدام خيارات stats.logging و infrastructureLogging لتمكين هذه الرسائل.
رسم بياني للوحدة والحزمة (Module and Chunk Graph)
كان Webpack يقوم بتخزين الوحدة المحللة (resolved module) في التبعية، وتخزين الوحدات المضمنة في الحزمة (chunk). لم يعد هذا هو الحال. يتم الآن تخزين جميع المعلومات حول كيفية توصيل الوحدات في الرسم البياني للوحدة (module graph) في فئة ModuleGraph. يتم الآن تخزين جميع المعلومات حول كيفية توصيل الوحدات بالحزم في فئة ChunkGraph. المعلومات التي تعتمد على سبيل المثال على الرسم البياني للحزمة، يتم تخزينها أيضًا في الفئة ذات الصلة.
هذا يعني أنه تم نقل المعلومات التالية حول الوحدات:
- Module connections -> ModuleGraph
- Module issuer -> ModuleGraph
- Module optimization bailout -> ModuleGraph (ملاحظة: تحقق مما إذا كان يجب أن يكون ChunkGraph بدلاً من ذلك)
- Module usedExports -> ModuleGraph
- Module providedExports -> ModuleGraph
- Module pre order index -> ModuleGraph
- Module post order index -> ModuleGraph
- Module depth -> ModuleGraph
- Module profile -> ModuleGraph
- Module id -> ChunkGraph
- Module hash -> ChunkGraph
- Module runtime requirements -> ChunkGraph
- Module is in chunk -> ChunkGraph
- Module is entry in chunk -> ChunkGraph
- Module is runtime module in chunk -> ChunkGraph
- Chunk runtime requirements -> ChunkGraph
كان Webpack يقوم بفصل الوحدات عن الرسم البياني عند استعادتها من ذاكرة التخزين المؤقت. لم يعد هذا ضروريًا. لا تقوم الوحدة (Module) بتخزين أي معلومات حول الرسم البياني ويمكن استخدامها تقنيًا في رسوم بيانية متعددة. هذا يجعل التخزين المؤقت أسهل.
هناك طبقة توافق لمعظم هذه التغييرات، والتي تطبع تحذير إهمال عند استخدامها.
الترحيل: استخدم واجهات برمجة التطبيقات (APIs) الجديدة على ModuleGraph و ChunkGraph
Init Fragments
تمت إزالة DependenciesBlockVariables لصالح InitFragments. يمكن الآن لـ DependencyTemplates إضافة InitFragments لحقن التعليمات البرمجية في أعلى مصدر الوحدة. تسمح InitFragments بإلغاء التكرار (deduplication).
الترحيل: استخدم InitFragments بدلاً من إدراج شيء ما في فهرس سالب (negative index) داخل المصدر.
أنواع مصادر الوحدة (Module Source Types)
يجب على الوحدات الآن تحديد أنواع المصادر (source types) التي تدعمها عبر Module.getSourceTypes(). اعتمادًا على ذلك، تستدعي الإضافات المختلفة source() باستخدام هذه الأنواع. على سبيل المثال، بالنسبة لنوع المصدر javascript، تقوم إضافة JavascriptModulesPlugin بتضمين الكود المصدري في الحزمة. سيؤدي نوع المصدر webassembly إلى قيام إضافة WebAssemblyModulesPlugin بإصدار ملف wasm. يتم دعم أنواع المصادر المخصصة أيضًا، على سبيل المثال من المحتمل أن تستخدم إضافة mini-css-extract-plugin نوع المصدر stylesheet لتضمين كود المصدر في ملف css.
لا توجد علاقة بين نوع الوحدة (module type) ونوع المصدر (source type). أي أن نوع الوحدة json يستخدم أيضًا نوع المصدر javascript ويستخدم نوع الوحدة webassembly/experimental أنواع المصدر javascript و webassembly.
الترحيل: تحتاج الوحدات المخصصة إلى تنفيذ طرق الواجهة الجديدة هذه.
إضافات الإحصائيات (Plugins for Stats)
الإحصائيات preset، default، json و toString مدمجة الآن بواسطة نظام إضافة (plugin system). تم تحويل الإحصائيات الحالية إلى إضافات.
الترحيل: بدلاً من استبدال وظيفة الإحصائيات بالكامل، يمكنك الآن تخصيصها. يمكن الآن إضافة معلومات إضافية إلى إحصائيات json بدلاً من كتابة ملف منفصل.
مراقبة جديدة (New Watching)
تمت إعادة هيكلة المراقب (watcher) الذي يستخدمه webpack. كان يستخدم سابقًا chokidar والتبعية الأصلية fsevents (فقط على نظام macOS). الآن يعتمد فقط على fs الخاص بـ Node.js الأصلي. هذا يعني أنه لم يتبق أي تبعية أصلية في webpack.
كما أنه يلتقط المزيد من المعلومات حول نظام الملفات أثناء المراقبة. يلتقط الآن أوقات التعديل (mtimes) ويراقب أوقات الأحداث (event times)، بالإضافة إلى معلومات حول الملفات المفقودة. لهذا الغرض، تغيرت واجهة WatchFileSystem قليلاً. أثناء القيام بذلك، قمنا أيضًا بتحويل المصفوفات (Arrays) إلى Sets والكائنات (Objects) إلى Maps.
SizeOnlySource بعد الإصدار
يستبدل Webpack الآن المصادر (Sources) في Compilation.assets بمتغيرات SizeOnlySource لتقليل استخدام الذاكرة.
إصدار الأصول مرات متعددة
تم تحويل التحذير (warning) Multiple assets emit different content to the same filename (محتوى مختلف لعدة أصول يتم إصداره بنفس اسم الملف) إلى خطأ (error).
ExportsInfo
تمت إعادة هيكلة الطريقة التي يتم بها تخزين المعلومات حول صادرات الوحدات (exports of modules). يحتوي ModuleGraph الآن على ExportsInfo لكل Module، والذي يقوم بتخزين المعلومات لكل تصدير. كما يقوم بتخزين معلومات حول الصادرات غير المعروفة وما إذا كانت الوحدة تُستخدم بطريقة لا تحتوي إلا على تأثيرات جانبية (side-effect-only).
بالنسبة لكل تصدير، يتم تخزين المعلومات التالية:
- هل التصدير مستخدم؟ نعم، لا، غير معروف بشكل ثابت (statically known)، غير محدد. (راجع أيضًا
optimization.usedExports) - هل التصدير مُقدم (provided)؟ نعم، لا، غير معروف بشكل ثابت، غير محدد. (راجع أيضًا
optimization.providedExports) - هل يمكن إعادة تسمية اسم التصدير؟ نعم، لا، غير محدد.
- الاسم الجديد، إذا تمت إعادة تسمية التصدير. (راجع أيضًا
optimization.mangleExports) ExportsInfoالمتداخلة، إذا كان التصدير عبارة عن كائن به معلومات مرفقة به- يُستخدم لإعادة تصدير كائنات مساحات الأسماء:
import * as X from "..."; export { X }; - يُستخدم لتمثيل البنية في وحدات JSON
- يُستخدم لإعادة تصدير كائنات مساحات الأسماء:
مرحلة توليد الكود (Code Generation Phase)
تتميز عملية التجميع (Compilation) بتوليد الكود كمرحلة تجميع منفصلة الآن. لم تعد تعمل بشكل مخفي في Module.source() أو Module.getRuntimeRequirements().
يجب أن يجعل هذا التدفق أكثر نظافة. كما يسمح بالإبلاغ عن التقدم المحرز في هذه المرحلة ويجعل توليد الكود أكثر وضوحًا عند إنشاء ملفات التعريف (profiling).
الترحيل: تم إهمال Module.source() و Module.getRuntimeRequirements() الآن. استخدم Module.codeGeneration() بدلاً من ذلك.
مرجع التبعية (DependencyReference)
كان لدى Webpack طريقة ونوع واحد لتمثيل مراجع التبعيات (تقوم Compilation.getDependencyReference بإرجاع DependencyReference).
كان هذا النوع يتضمن جميع المعلومات حول هذا المرجع مثل الوحدة (Module) المُشار إليها، وأسماء الصادرات التي تم استيرادها، وما إذا كان مرجعًا ضعيفًا (weak reference) وكذلك بعض المعلومات المتعلقة بالترتيب.
يؤدي تجميع كل هذه المعلومات معًا إلى جعل الحصول على المرجع أمرًا مكلفًا ويتم استدعاؤه بشكل متكرر (في كل مرة يحتاج فيها شخص ما إلى معلومة واحدة).
في webpack 5، تمت إعادة هيكلة هذا الجزء من قاعدة الكود وتم تقسيم الطريقة (method).
- يمكن قراءة الوحدة المشار إليها من
ModuleGraphConnection - يمكن الحصول على أسماء الصادرات المستوردة عبر
Dependency.getReferencedExports() - توجد علامة
weak(ضعيف) على فئةDependency - الترتيب وثيق الصلة فقط بـ
HarmonyImportDependenciesويمكن الحصول عليه عبر خاصيةsourceOrder
تبعيات العرض (Presentational Dependencies)
يوجد الآن نوع جديد من التبعية في NormalModules: التبعيات التقديمية (Presentational Dependencies)
تُستخدم هذه التبعيات فقط أثناء مرحلة "توليد الكود" (Code Generation) ولكن لا تُستخدم أثناء بناء الرسم البياني للوحدة (Module Graph). لذا لا يمكن أن يكون لديها وحدات مرجعية أو تؤثر على الصادرات/الواردات.
هذه التبعيات أرخص في المعالجة ويستخدمها webpack عندما يكون ذلك ممكنًا.
محملات مهملة (Deprecated loaders)
-
سيتم إهماله. استخدم
module.exports = { resolve: { alias: { xyz$: false, }, }, };أو استخدم مسارًا مطلقًا (absolute path)
module.exports = { resolve: { alias: { [path.resolve(__dirname, "....")]: false, }, }, };
تغييرات طفيفة (Minor Changes)
Compiler.name: عند إنشاء اسم مترجم (compiler name) بمسارات مطلقة، تأكد من فصلها باستخدام|أو!في كلا جزأي الاسم.- أصبح استخدام المسافة (space) كفاصل مهملًا الآن. (يمكن أن تحتوي المسارات على مسافات)
- تلميح: يتم استبدال
|بمسافة في إخراج سلسلة الإحصائيات (Stats string output).
- يتم الآن تعطيل
SystemPluginافتراضيًا.- الترحيل: تجنب استخدامه حيث تمت إزالة المواصفات (spec). يمكنك إعادة تمكينه باستخدام
Rule.parser.system: true
- الترحيل: تجنب استخدامه حيث تمت إزالة المواصفات (spec). يمكنك إعادة تمكينه باستخدام
ModuleConcatenationPlugin: لم يعد التسلسل (concatenation) يُمنع بواسطةDependencyVariablesحيث تمت إزالتها- هذا يعني أنه يمكن الآن التسلسل في حالات
module،global،processأو الـProvidePlugin
- هذا يعني أنه يمكن الآن التسلسل في حالات
- إزالة
Stats.presetToOptions- الترحيل: استخدم
compilation.createStatsOptionsبدلاً من ذلك
- الترحيل: استخدم
- إزالة
SingleEntryPluginوSingleEntryDependency- الترحيل: استخدم
EntryPluginوEntryDependency
- الترحيل: استخدم
- يمكن أن تحتوي الحزم (Chunks) الآن على وحدات دخول (entry modules) متعددة
- إزالة
ExtendedAPIPlugin- الترحيل: لم يعد هناك حاجة إليها، يمكن دائمًا استخدام
__webpack_hash__و__webpack_chunkname__ويتم حقن كود وقت التشغيل عند الحاجة.
- الترحيل: لم يعد هناك حاجة إليها، يمكن دائمًا استخدام
- لم يعد
ProgressPluginيستخدم سياق tapable لـreportProgress- الترحيل: استخدم
ProgressPlugin.getReporter(compiler)بدلاً من ذلك
- الترحيل: استخدم
- تمت إعادة تفعيل
ProvidePluginالآن لملفات.mjs - لم تعد الأخطاء والتحذيرات في ملفات الإحصائيات (
Statsjsonerrorsandwarnings) تحتوي على سلاسل نصية (strings) بل أصبحت تحتوي على كائنات بمعلومات مقسمة إلى خصائص.- الترحيل: قم بالوصول إلى المعلومات على الخصائص. مثل
message
- الترحيل: قم بالوصول إلى المعلومات على الخصائص. مثل
- إهمال
Compilation.hooks.normalModuleLoader- الترحيل: استخدم
NormalModule.getCompilationHooks(compilation).loaderبدلاً من ذلك
- الترحيل: استخدم
- تغيير الخطافات في
NormalModuleFactoryمن المتتالية (waterfall) إلى المنسحبة (bailing)، وتغيير وإعادة تسمية الخطافات التي تُرجع وظائف متتالية (waterfall functions) - إزالة
compilationParams.compilationDependencies- يمكن للإضافات إضافة تبعيات إلى التجميع (compilation) عن طريق إضافتها إلى
compilation.file/context/missingDependencies - ستقوم طبقة التوافق بتفويض
compilationDependencies.addإلىfileDependencies.add
- يمكن للإضافات إضافة تبعيات إلى التجميع (compilation) عن طريق إضافتها إلى
- أصبح
stats.assetsByChunkName[x]الآن دائمًا مصفوفة (array) - تمت إضافة دالة
__webpack_get_script_filename__للحصول على اسم ملف نص برمجي (script file) - سيتم التعامل مع
"sideEffects"في package.json بواسطةglob-to-regexبدلاً منmicromatch- قد يؤدي هذا إلى تغيير الدلالات (semantics) في الحالات القصوى (edge-cases)
- تمت إزالة
checkContextمنIgnorePlugin - واجهة برمجة تطبيقات (API) جديدة
__webpack_exports_info__تتيح استبطان (introspection) استخدام التصدير - تُطبق إضافة
SourceMapDevToolPluginعلى الأصول غير الحزمية (non-chunk assets) الآن أيضًا - تعرض
EnvironmentPluginخطأ الآن عند فقدان متغير البيئة المُشار إليه وعدم وجود بديل له (no fallback) - إزالة خاصية
serveمن المخطط (schema)
تغييرات طفيفة أخرى (Other Minor Changes)
- إزالة الدليل المُدمج (builtin directory) واستبدال المدمجات (builtins) بوحدات وقت التشغيل
- إزالة الميزات المهملة
- تدعم
BannerPluginالآن وسيطًا واحدًا فقط يمكن أن يكون كائنًا (object) أو سلسلة نصية (string) أو دالة (function)
- تدعم
- إزالة
CachePlugin - تم إهمال
Chunk.entryModule، استخدمChunkGraphبدلاً من ذلك - إهمال
Chunk.hasEntryModule - إهمال
Chunk.addModule - إهمال
Chunk.removeModule - إهمال
Chunk.getNumberOfModules - إهمال
Chunk.modulesIterable - إهمال
Chunk.compareTo - إهمال
Chunk.containsModule - إهمال
Chunk.getModules - إهمال
Chunk.remove - إهمال
Chunk.moveModule - إهمال
Chunk.integrate - إهمال
Chunk.canBeIntegrated - إهمال
Chunk.isEmpty - إهمال
Chunk.modulesSize - إهمال
Chunk.size - إهمال
Chunk.integratedSize Chunk.getChunkModuleMapsis deprecated- إهمال
Chunk.hasModuleInGraph - تغيير توقيع (signature)
Chunk.updateHash - تغيير توقيع
Chunk.getChildIdsByOrders(ملاحظة: فكر في نقله إلىChunkGraph) - تغيير توقيع
Chunk.getChildIdsByOrdersMap(ملاحظة: فكر في نقله إلىChunkGraph) - إزالة
Chunk.getChunkModuleMaps - إزالة
Chunk.setModules - إزالة طرق Chunk المهملة (deprecated Chunk methods)
- إضافة
ChunkGraph - إزالة
ChunkGroup.setParents - إزالة
ChunkGroup.containsModule - تمت إزالة
Compilation.cacheلصالحCompilation.getCache() - لم يعد
ChunkGroup.removeيفصل المجموعة عن الكتلة (block) - تغيير توقيع
ChunkGroup.compareTo - تغيير توقيع
ChunkGroup.getChildrenByOrders - تم تغيير اسم index و index في
ChunkGroupإلى index للترتيب المسبق/اللاحق (pre/post order index)- تم إهمال المسترد (getter) القديم
- تغيير توقيع
ChunkTemplate.hooks.modules - تغيير توقيع
ChunkTemplate.hooks.render - تغيير توقيع
ChunkTemplate.updateHashForChunk - إزالة
Compilation.hooks.optimizeChunkOrder - إزالة
Compilation.hooks.optimizeModuleOrder - إزالة
Compilation.hooks.advancedOptimizeModuleOrder - إزالة
Compilation.hooks.optimizeDependenciesBasic - إزالة
Compilation.hooks.optimizeDependenciesAdvanced - إزالة
Compilation.hooks.optimizeModulesBasic - إزالة
Compilation.hooks.optimizeModulesAdvanced - إزالة
Compilation.hooks.optimizeChunksBasic - إزالة
Compilation.hooks.optimizeChunksAdvanced - إزالة
Compilation.hooks.optimizeChunkModulesBasic - إزالة
Compilation.hooks.optimizeChunkModulesAdvanced - إزالة
Compilation.hooks.optimizeExtractedChunksBasic - إزالة
Compilation.hooks.optimizeExtractedChunks - إزالة
Compilation.hooks.optimizeExtractedChunksAdvanced - إزالة
Compilation.hooks.afterOptimizeExtractedChunks - إضافة
Compilation.hooks.stillValidModule - إضافة
Compilation.hooks.statsPreset - إضافة
Compilation.hooks.statsNormalize - إضافة
Compilation.hooks.statsFactory - إضافة
Compilation.hooks.statsPrinter - أصبحت
Compilation.fileDependencies،Compilation.contextDependenciesوCompilation.missingDependenciesالآنLazySets - إزالة
Compilation.entries- الترحيل: استخدم
Compilation.entryDependenciesبدلاً من ذلك
- الترحيل: استخدم
- إزالة
Compilation._preparedEntrypoints - أصبح
dependencyTemplatesالآن فئة (class)DependencyTemplatesبدلاً منMapخام - إزالة
Compilation.fileTimestampsوcontextTimestamps- الترحيل: استخدم
Compilation.fileSystemInfoبدلاً من ذلك
- الترحيل: استخدم
- إزالة
Compilation.waitForBuildingFinished- الترحيل: استخدم الطوابير (queues) الجديدة
- إزالة
Compilation.addModuleDependencies - إزالة
Compilation.prefetch - يتم الآن استدعاء
Compilation.hooks.beforeHashبعد إنشاء التجزئات (hashes) الخاصة بالوحدات- الترحيل: استخدم
Compilation.hooks.beforeModuleHashبدلاً من ذلك
- الترحيل: استخدم
- إزالة
Compilation.applyModuleIds - إزالة
Compilation.applyChunkIds - تمت إضافة
Compiler.root، والذي يشير إلى المترجم الأساسي (root compiler)- يمكن استخدامه لتخزين البيانات مؤقتًا في
WeakMapsبدلاً من أن يكون نطاقها ثابتًا (statically scoped)
- يمكن استخدامه لتخزين البيانات مؤقتًا في
- إضافة
Compiler.hooks.afterDone - لم يعد
Source.emittedيتم تعيينه بواسطة المترجم (Compiler)- الترحيل: تحقق من
Compilation.emittedAssetsبدلاً من ذلك
- الترحيل: تحقق من
- إضافة
Compiler/Compilation.compilerPath: إنه اسم فريد للمترجم في شجرة المترجمين. (فريد لنطاق المترجم الأساسي - root compiler scope) - إهمال
Module.needRebuild- الترحيل: استخدم
Module.needBuildبدلاً من ذلك
- الترحيل: استخدم
- تغيير توقيع
Dependency.getReference - تغيير توقيع
Dependency.getExports - تغيير توقيع
Dependency.getWarnings - تغيير توقيع
Dependency.getErrors - تغيير توقيع
Dependency.updateHash - إزالة
Dependency.module - يوجد الآن فئة أساسية (base class) لـ
DependencyTemplate - إزالة
MultiEntryDependency - إضافة
EntryDependency - إزالة
EntryModuleNotFoundError - إزالة
SingleEntryPlugin - إضافة
EntryPlugin - إضافة
Generator.getTypes - إضافة
Generator.getSize - تغيير توقيع
Generator.generate - إضافة
HotModuleReplacementPlugin.getParserHooks - تم نقل
ParserإلىJavascriptParser - تم نقل
ParserHelpersإلىJavascriptParserHelpers - إزالة
MainTemplate.hooks.moduleObj - إزالة
MainTemplate.hooks.currentHash - إزالة
MainTemplate.hooks.addModule - إزالة
MainTemplate.hooks.requireEnsure - إزالة
MainTemplate.hooks.globalHashPaths - إزالة
MainTemplate.hooks.globalHash - إزالة
MainTemplate.hooks.hotBootstrap - تغيير بعض التوقيعات لـ
MainTemplate.hooks - إهمال
Module.hash - إهمال
Module.renderedHash - إزالة
Module.reasons - إهمال
Module.id - إهمال
Module.index - إهمال
Module.index2 - إهمال
Module.depth - إهمال
Module.issuer - إزالة
Module.profile - إزالة
Module.prefetched - إزالة
Module.built - إزالة
Module.used- الترحيل: استخدم
Module.getUsedExportsبدلاً من ذلك
- الترحيل: استخدم
- إهمال Module.usedExports
- الترحيل: استخدم
Module.getUsedExportsبدلاً من ذلك
- الترحيل: استخدم
- إهمال
Module.optimizationBailout - إزالة
Module.exportsArgument - إهمال
Module.optional - إزالة
Module.disconnect - إزالة
Module.unseal - إزالة
Module.setChunks - إهمال
Module.addChunk - إهمال
Module.removeChunk - إهمال
Module.isInChunk - إهمال
Module.isEntryModule - إهمال
Module.getChunks - إهمال
Module.getNumberOfChunks - إهمال
Module.chunksIterable - إزالة
Module.hasEqualsChunks - تم نقل
Module.useSourceMapإلىNormalModule - إزالة
Module.addReason - إزالة
Module.removeReason - إزالة
Module.rewriteChunkInReasons - إزالة
Module.isUsed- الترحيل: استخدم
isModuleUsed،isExportUsedوgetUsedNameبدلاً من ذلك
- الترحيل: استخدم
- تغيير توقيع
Module.updateHash - إزالة
Module.sortItems - إزالة
Module.unbuild- الترحيل: استخدم
invalidateBuildبدلاً من ذلك
- الترحيل: استخدم
- إضافة
Module.getSourceTypes - إضافة
Module.getRuntimeRequirements - تغيير توقيع
Module.size - تغيير توقيع
ModuleFilenameHelpers.createFilename - إضافة فئة
ModuleProfileمع مزيد من البيانات - إزالة
ModuleReason - تغيير توقيعات
ModuleTemplate.hooks - تغيير توقيع
ModuleTemplate.render - إزالة
Compiler.dependencies- الترحيل: استخدم
MultiCompiler.setDependenciesبدلاً من ذلك
- الترحيل: استخدم
- إزالة
MultiModule - إزالة
MultiModuleFactory - أصبحت
NormalModuleFactory.fileDependencies،NormalModuleFactory.contextDependenciesوNormalModuleFactory.missingDependenciesالآنLazySets - تأخذ طرق
RuntimeTemplateالآن وسطاء (arguments)runtimeRequirements - تمت إزالة خاصية
serve - إزالة
Stats.jsonToString - إزالة
Stats.filterWarnings - إزالة
Stats.getChildOptions - إزالة الطرق المساعدة (helper methods) لـ
Stats - تغيير توقيع
Stats.toJson(تمت إزالة الوسيط الثاني) - إزالة
ExternalModule.external - إزالة
HarmonyInitDependency - إهمال
Dependency.getInitFragments- الترحيل: استخدم
applyinitFragmentsبدلاً من ذلك
- الترحيل: استخدم
- يأخذ
DependencyReferenceالآن دالة لوحدة (function to a module) بدلاً منModule - إزالة
HarmonyImportSpecifierDependency.redirectedId- الترحيل: استخدم
setIdبدلاً من ذلك
- الترحيل: استخدم
- acorn من الإصدار 5 -> 8
- الاختبار (Testing)
- تعمل HotTestCases الآن لأهداف متعددة
async-nodenodewebwebworker - تعمل TestCases الآن أيضًا للتخزين المؤقت لنظام الملفات باستخدام
store: "instant"وstore: "pack" - تعمل TestCases الآن أيضًا لمعرفات الوحدات الحتمية (deterministic module ids)
- تعمل HotTestCases الآن لأهداف متعددة
- تمت إضافة أدوات لترتيب الواردات (imports) (يتم التحقق منها في CI)
- لم يعد تعيين اسم الحزمة في وقت التشغيل (Chunk name mapping in runtime) يحتوي على إدخالات (entries) عندما يساوي اسم الحزمة معرف الحزمة
- إضافة
resolvedModuleId،resolvedModuleIdentifierوresolvedModuleإلى الأسباب (reasons) في الإحصائيات (Stats) والتي تشير إلى الوحدة قبل التحسينات مثل رفع النطاق (scope hoisting) - عرض
resolvedModuleفي إخراجStatstoString - تمت ترقية loader-runner: https://github.com/webpack/loader-runner/releases/tag/v3.0.0
- لم تعد
file/context/missingDependenciesفيCompilationمفروزة لأسباب تتعلق بالأداء- لا تعتمد على الترتيب
- تمت ترقية webpack-sources إلى الإصدار 2: https://github.com/webpack/webpack-sources/releases/tag/v2.0.1
- تمت إزالة دعم webpack-command
- استخدم schema-utils@2 للتحقق من صحة المخطط (schema validation)
- يحتوي
Compiler.assetEmittedعلى وسيط ثانٍ مُحسن بمزيد من المعلومات - يقوم
BannerPluginبحذف المسافات الزائدة (trailing whitespace) - تمت إزالة خيار
minChunkSizeمنLimitChunkCountPlugin - إعادة التنظيم من الملفات المتعلقة بجافا سكريبت إلى دليل فرعي (sub-directory)
webpack.JavascriptModulesPlugin->webpack.javascript.JavascriptModulesPlugin
- إضافة Logger.getChildLogger
- تغيير الإعداد الافتراضي لـ
entryOnlyفي DllPlugin إلىtrue - إزالة منطق تقصير الطلب الخاص (special request shortening logic) واستخدام مسارات نسبية مفردة (single relative paths) لأسماء وحدات قابلة للقراءة
- السماح لعناوين webpack:// urls في SourceMaps بالمسارات المقدمة المتعلقة بالسياق الأساسي لـ webpack (webpack root context)
- إضافة واجهة برمجة تطبيقات (API) لإنشاء ومعالجة وسيطات CLI التي تستهدف تكوين webpack
- إضافة
__system_context__كسياق (context) من System.js عند استخدام System.js كـ libraryTarget - إضافة دعم bigint لإضافة DefinePlugin
- إضافة دعم bigint للتقييمات الأساسية (basic evaluations) مثل الرياضيات
- إزالة القدرة على تعديل تجزئة التجميع (compilation hash) بعد إنشاء التجزئة
- إزالة وضع الخطوات المتعددة (multiStep mode) لإضافة HotModuleReplacementPlugin
- سوف تندمج الآن
assetInfoمنemitAssetعند استخدام الكائنات أو المصفوفات المتداخلة (nested objects or arrays) - يعد
[query]الآن عنصرًا نائبًا (placeholder) صالحًا للمسارات بناءً علىfilenameمثل الأصول (assets) - إضافة
Compilation.deleteAssetلحذف الأصول (assets) والأصول غير المشتركة ذات الصلة بشكل صحيح - عرض
require("webpack-sources")على هيئةrequire("webpack").sources - terser 5
- يمكن كتابة Webpack بحرف W كبير عندما يكون في بداية جملة



