من v4 إلى v5
يهدف هذا الدليل إلى مساعدتك على الترقية إلى webpack 5 عندما تستخدم webpack مباشرة. إذا كنت تستخدم أداة أعلى مستوى لتشغيل webpack، فارجع إلى تلك الأداة لمعرفة تعليمات الترقية.
التحضيرات
يتطلب Webpack 5 إصدار Node.js 10.13.0 على الأقل (LTS)، لذلك تأكد من ترقية Node.js إذا كنت ما زلت تستخدم إصدارًا أقدم.
ترقية webpack 4 وplugins/loaders الخاصة به
-
رقّ
webpack4 إلى أحدث إصدار متاح.-
عند استخدام webpack >= 4، لا ينبغي أن تحتاج الترقية إلى أحدث إصدار من webpack 4 إلى إرشادات إضافية.
-
إذا كنت تستخدم إصدار webpack أقل من 4، فراجع دليل الترقية إلى webpack 4.
-
-
رقّ
webpack-cliإلى أحدث إصدار متاح عند استخدامه. -
رقّ كل Plugins وLoaders المستخدمة إلى أحدث إصدار متاح.
قد يكون لبعض Plugins وLoaders إصدار beta يجب استخدامه ليكون متوافقًا مع webpack 5. تأكد من قراءة release notes لكل plugin/loader عند ترقيته؛ فقد يدعم أحدث إصدار webpack 5 فقط ويفشل مع v4. في هذه الحالة، يُنصح بالتحديث إلى أحدث إصدار يدعم webpack 4.
Codemods
للمساعدة في الترقية من webpack v4 إلى v5، يوفر Codemod codemods مجتمعية مفتوحة المصدر يمكنها أتمتة معظم عملية الترقية.
لاحظ أن هذه codemods ليست رسمية من webpack. ورغم أنها تهدف إلى تسهيل الترقية، فقد لا تغطي كل الحالات. قد تحتاج إلى خطوات يدوية إضافية لإكمال الترقية بالكامل.
شغّل webpack v5 migration codemods:
npx codemod@latest webpack/v5/migration-recipeسيشغّل هذا codemods التالية من Codemod registry:
webpack/v5/set-target-to-false-and-update-pluginswebpack/v5/migrate-library-target-to-library-objectwebpack/v5/json-imports-to-default-imports
كل واحد من هذه codemods يؤتمت تغييرًا مذكورًا في دليل الترقية إلى webpack v5. للقائمة الكاملة من codemods المتاحة لـ webpack v5، راجع Codemod Registry.
تأكد من أن build لا يحتوي على أخطاء أو تحذيرات
قد تظهر أخطاء أو تحذيرات جديدة بسبب الإصدارات المحدثة من webpack وwebpack-cli وPlugins وLoaders. انتبه لتحذيرات deprecation أثناء build.
يمكنك تشغيل webpack بهذه الطريقة للحصول على stack traces لتحذيرات deprecation ومعرفة Plugins وLoaders المسؤولة عنها.
node --trace-deprecation node_modules/webpack/bin/webpack.jsلأن webpack 5 يزيل كل الميزات المهملة، تأكد من عدم وجود تحذيرات deprecation من webpack أثناء build قبل المتابعة.
تأكد من استخدام mode
اضبط mode على production أو development للتأكد من تطبيق defaults المناسبة.
حدّث الخيارات القديمة
حدّث الخيارات التالية إلى صيغتها الجديدة إذا كنت تستخدمها:
optimization.hashedModuleIds: true→optimization.moduleIds: 'hashed'optimization.namedChunks: true→optimization.chunkIds: 'named'optimization.namedModules: true→optimization.moduleIds: 'named'NamedModulesPlugin→optimization.moduleIds: 'named'NamedChunksPlugin→optimization.chunkIds: 'named'HashedModuleIdsPlugin→optimization.moduleIds: 'hashed'optimization.noEmitOnErrors: false→optimization.emitOnErrors: trueoptimization.occurrenceOrder: true→optimization: { chunkIds: 'total-size', moduleIds: 'size' }optimization.splitChunks.cacheGroups.vendors→optimization.splitChunks.cacheGroups.defaultVendorsoptimization.splitChunks.cacheGroups.test(module, chunks)→optimization.splitChunks.cacheGroups.test(module, { chunkGraph, moduleGraph })Compilation.entries→Compilation.entryDependenciesserve→ تمت إزالةserveلصالحDevServerRule.query(مهمل منذ v3) →Rule.options/UseEntry.optionsRule.loaders→Rule.use
اختبر توافق webpack 5
جرّب ضبط الخيارات التالية داخل إعداد webpack 4 لديك وتحقق من أن build ما زال يعمل بشكل صحيح.
export default {
// ...
node: {
Buffer: false,
process: false,
},
};يجب إزالة هذه الخيارات مرة أخرى عند ترقية إعدادك إلى webpack 5.
ترقية webpack إلى 5
الآن لنرقّ webpack إلى الإصدار 5:
-
npm:
npm install webpack@latest -
Yarn:
yarn add webpack@latest -
pnpm:
pnpm add webpack@latest
إذا لم تستطع ترقية بعض plugins/loaders إلى أحدث إصدار في خطوة ترقية webpack 4 وplugins/loaders الخاصة به، فلا تنس ترقيتها الآن.
تنظيف الإعدادات
-
فكر في إزالة
optimization.moduleIdsوoptimization.chunkIdsمن إعدادات webpack. قد تكون defaults أفضل، لأنها تدعم long term caching فيproduction modeوdebugging فيdevelopmentmode. -
إذا كنت تستخدم placeholder
[hash]في إعدادات webpack، ففكر في تغييره إلى[contenthash]. ليسا الشيء نفسه، لكن[contenthash]أثبت أنه أكثر فعالية. -
إذا كنت تستخدم Yarn PnP و
pnp-webpack-plugin، فهناك خبر جيد: أصبح مدعومًا افتراضيًا الآن. يجب إزالته من الإعدادات. -
إذا كنت تستخدم
IgnorePluginمع regular expression كـ argument، فهو الآن يأخذ كائنoptions:new IgnorePlugin({ resourceRegExp: /regExp/ }). -
إذا كنت تستخدم شيئًا مثل
node.fs: 'empty'فاستبدله بـresolve.fallback.fs: false. -
إذا كنت تستخدم
watch: trueفي webpack Node.js API، فأزله. لا حاجة لضبطه لأنه يُفهم من دالة compiler التي تستدعيها، إماtrueعندwatch()أوfalseعندrun(). -
إذا كانت لديك
rulesلتحميل assets باستخدامraw-loaderأوurl-loaderأوfile-loader، فاستخدم Asset Modules بدلًا منها لأنها ستُهمل في المستقبل القريب. -
إذا كان
targetلديك مضبوطًا على دالة، فحدّثه إلىfalseوطبّق تلك الدالة داخل خيارplugins. راجع المثال:// في webpack 4 { target: WebExtensionTarget(nodeConfig) } // في webpack 5 { target: false, plugins: [ WebExtensionTarget(nodeConfig) ] }ملاحظة: يوجد Codemod لهذا التغيير:
npx codemod webpack/v5/set-target-to-false-and-update-plugins(راجع registry هنا.)
-
إذا كان لديك
output.libraryأوoutput.libraryTarget، فغيّر أسماء الخصائص:output.libraryTargetتصبحoutput.library.type، وoutput.libraryتصبحoutput.library.name. مثال:// في webpack 4 { output: { library: 'MyLibrary', libraryTarget: 'commonjs2' } } // في webpack 5 { output: { library: { name: 'MyLibrary', type: 'commonjs2' } } }ملاحظة: يوجد Codemod لهذا التغيير:
npx codemod webpack/v5/migrate-library-target-to-library-object(راجع registry هنا.)
إذا كنت تستخدم WebAssembly عبر import، فاتبع هذه العملية من خطوتين:
- فعّل المواصفة المهملة بضبط
experiments.syncWebAssembly: trueللحصول على السلوك نفسه الموجود في webpack 4. - بعد نجاح الترقية إلى webpack 5، غيّر قيمة
experimentsإلىexperiments: { asyncWebAssembly: true }لاستخدام المواصفة الأحدث لتكامل WASM.
أعد التفكير في optimization.splitChunks:
- يُنصح باستخدام defaults أو
optimization.splitChunks: { chunks: 'all' }. - عند استخدام إعداد مخصص، احذف
name: falseواستبدلname: string | functionبـidHint: string | function. - كان ممكنًا تعطيل defaults بضبط
optimization.splitChunks.cacheGroups: { default: false, vendors: false }. لا نوصي بذلك، لكن إذا كنت تريد الأثر نفسه في webpack 5: استخدمoptimization.splitChunks.cacheGroups: { default: false, defaultVendors: false }.
فكر في إزالة defaults:
- عند استخدام
entry: './src/index.js': يمكنك حذفها، لأنها القيمة الافتراضية. - عند استخدام
output.path: path.resolve(__dirname, 'dist'): يمكنك حذفها، لأنها القيمة الافتراضية. - عند استخدام
output.filename: '[name].js': يمكنك حذفها، لأنها القيمة الافتراضية.
هل تحتاج إلى دعم متصفح قديم مثل IE 11؟
-
إذا كان browserslist مفعّلًا في مشروعك، فسيعيد webpack 5 استخدام إعداد
browserslistلتحديد أسلوب الكود الذي سيصدره runtime.تأكد من:
- ضبط
targetعلىbrowserslistأو حذفtargetوترك webpack يضبطbrowserslistتلقائيًا. - إضافة
IE 11إلى إعداد browserslist لديك.
- ضبط
-
بدون
browserslist، يستخدم runtime code الخاص بـ webpack صيغة ES2015، مثل arrow function، لإنتاج bundles أصغر. لذلك ستحتاج إلى ضبطtarget: ['web', 'es5']لاستخدام صيغة ES5 للمتصفحات التي لا تدعم ES2015 مثل IE11. -
بالنسبة إلى Node.js، تتضمن builds إصدار Node.js المدعوم داخل خيار
target، وسيعرف webpack تلقائيًا أي syntax مدعوم، مثلtarget: 'node8.6'.
تنظيف الكود
استخدام /* webpackChunkName: '...' */
تأكد من فهم الهدف:
- اسم chunk هنا مقصود أن يكون عامًا.
- ليس اسمًا خاصًا بالتطوير فقط.
- سيستخدمه webpack لتسمية الملفات في production وdevelopment modes.
- سيعين webpack 5 أسماء ملفات مفيدة تلقائيًا في
developmentmode حتى بدون استخدامwebpackChunkName.
استخدام named exports من JSON modules
هذا غير مدعوم في المواصفة الجديدة وستحصل على تحذير. بدلًا من:
import { version } from "./package.json";
console.log(version);استخدم:
import pkg from "./package.json";
console.log(pkg.version);ملاحظة: يوجد Codemod لهذا التغيير:
npx codemod webpack/v5/json-imports-to-default-imports(راجع registry هنا.)
تنظيف كود build
- عند استخدام
const compiler = webpack(...);، تأكد من إغلاق compiler بعد استخدامه:compiler.close(callback);.- لا ينطبق هذا على صيغة
webpack(..., callback)لأنها تُغلق تلقائيًا. - هذا اختياري إذا كنت تستخدم webpack في watching mode حتى ينهي المستخدم العملية. ستُستخدم idle phases في watch mode لهذا النوع من العمل.
- لا ينطبق هذا على صيغة
شغّل build واحدًا واتبع النصائح
تأكد من قراءة أخطاء وتحذيرات build بعناية. إذا لم توجد نصيحة مقابلة، أنشئ issue وسنحاول حلها.
كرر الخطوات التالية حتى تحل المستوى 3 أو 4 على الأقل:
-
المستوى 1: فشل Schema validation.
تغيرت خيارات الإعداد. يجب أن يظهر validation error يحتوي على ملاحظة
BREAKING CHANGE:، أو تلميح للخيار الذي يجب استخدامه بدلًا من القديم. -
المستوى 2: ينهي Webpack العمل بخطأ.
يجب أن تخبرك رسالة الخطأ بما يحتاج إلى تغيير.
-
المستوى 3: Build Errors.
يجب أن تحتوي رسالة الخطأ على ملاحظة
BREAKING CHANGE:. -
المستوى 4: Build Warnings.
يجب أن تخبرك رسالة التحذير بما يمكن تحسينه.
-
المستوى 5: Runtime Errors.
هذا أصعب. غالبًا ستحتاج إلى debugging لمعرفة المشكلة. تقديم نصيحة عامة هنا صعب، لكن هذه بعض النصائح الشائعة المتعلقة بـ Runtime Errors:
processغير معرّف.- لم يعد webpack 5 يضيف polyfill لهذا المتغير الخاص بـ Node.js. تجنب استخدامه في كود frontend.
- تريد دعم الاستخدام في المتصفح؟ استخدم حقلي
exportsأوimportsداخل package.json لاختيار كود مختلف حسب البيئة.- استخدم أيضًا حقل
browserلدعم bundlers القديمة. - بديل آخر: غلّف أجزاء الكود بفحوصات
typeof process. لاحظ أن هذا يؤثر سلبًا في حجم bundle.
- استخدم أيضًا حقل
- تريد استخدام environment variables عبر
process.env.VARIABLE؟ تحتاج إلى استخدامDefinePluginأوEnvironmentPluginلتعريف هذه المتغيرات في الإعدادات.- فكر في استخدام
VARIABLEبدلًا من ذلك، وتأكد من فحصtypeof VARIABLE !== 'undefined'أيضًا.process.envخاص بـ Node.js ويجب تجنبه في كود frontend.
- فكر في استخدام
- أخطاء 404 تشير إلى URLs تحتوي على
auto.- ليست كل أدوات ecosystem جاهزة للقيمة الافتراضية الجديدة للـ
publicPathالتلقائي عبرoutput.publicPath: "auto".- استخدم
output.publicPath: ""ثابتًا بدلًا من ذلك.
- استخدم
- ليست كل أدوات ecosystem جاهزة للقيمة الافتراضية الجديدة للـ
- Cannot read properties of undefined (reading 'call')
- إذا رأيت هذا الخطأ وقت runtime، فقد يكون مرتبطًا بـ ModuleConcatenationPlugin. تحقق مما إذا كنت تستخدم plugin، وإذا كنت أضفته إلى قسم
pluginsفي إعداد ما وكان ذلك الإعداد مضبوطًا أيضًا علىproductionmode، فأزل plugin، أيnew webpack.optimize.ModuleConcatenationPlugin()، من قائمة plugins. في webpack 5، هذا plugin مفعّل افتراضيًا في production mode، وقد تتم إضافته مرتين. - بشكل عام، تعطيل كل plugin واختبار build طريقة جيدة لتحديد مصدر المشكلة.
- راجع هذه المناقشة لمزيد من التفاصيل.
- إذا رأيت هذا الخطأ وقت runtime، فقد يكون مرتبطًا بـ ModuleConcatenationPlugin. تحقق مما إذا كنت تستخدم plugin، وإذا كنت أضفته إلى قسم
-
المستوى 6: Deprecation Warnings.
غالبًا ستظهر لك تحذيرات deprecation كثيرة. هذا ليس مشكلة مباشرة. تحتاج plugins وقتًا للحاق بتغييرات core. يرجى إبلاغ مؤلفي plugins بهذه التحذيرات. هذه التحذيرات مجرد warnings وسيظل build يعمل مع عيوب بسيطة فقط، مثل أداء أقل.
- يمكنك إخفاء تحذيرات deprecation بتشغيل node مع flag
--no-deprecation، مثل:node --no-deprecation node_modules/webpack/bin/webpack.js. يجب أن يكون هذا حلًا مؤقتًا فقط. - يمكن لمساهمي Plugins وLoaders اتباع النصائح الموجودة في رسائل deprecation لتحسين الكود.
- يمكنك إخفاء تحذيرات deprecation بتشغيل node مع flag
-
المستوى 7: مشاكل الأداء.
عادةً يجب أن يتحسن الأداء مع webpack 5، لكن توجد حالات قليلة قد يسوء فيها الأداء.
وهذه أشياء يمكنك فعلها لتحسين الوضع:
- اعمل profile لمعرفة أين يذهب الوقت.
- يعرض
--profile --progressالآن profile أداء بسيطًا. - استخدم
node --inspect-brk node_modules/webpack/bin/webpack.jsمعchrome://inspectأوedge://inspect، ثم راجع تبويب profiler.- يمكنك حفظ هذه profiles كملفات وإرفاقها في issues.
- جرّب استخدام flag
--no-turbo-inliningللحصول على stack traces أفضل في بعض الحالات.
- يعرض
- يمكن تحسين وقت بناء modules في incremental builds بالرجوع إلى unsafe caching كما في webpack 4:
module.unsafeCache: true- لكن هذا قد يؤثر في القدرة على التعامل مع بعض تغييرات code base.
- Full build
- طبقة التوافق مع الميزات المهملة غالبًا أبطأ من الميزات الجديدة.
- إنشاء warnings كثيرة قد يؤثر في أداء build حتى لو تم تجاهلها.
- Source Maps مكلفة. راجع خيار
devtoolفي التوثيق للمقارنة بين الخيارات المختلفة. - حماية Anti-Virus قد تؤثر في أداء الوصول إلى نظام الملفات.
- Persistent Caching يمكن أن يساعد في تحسين full builds المتكررة.
- Module Federation يسمح بتقسيم التطبيق إلى عدة builds أصغر.
- اعمل profile لمعرفة أين يذهب الوقت.
كل شيء يعمل؟
يرجى التغريد بأنك نجحت في الترقية إلى webpack 5. غرّد بذلك
لا يعمل؟
أنشئ issue وأخبرنا بالمشاكل التي واجهتها أثناء الترقية.
يوجد شيء ناقص في هذا الدليل؟
افتح Pull Request لمساعدة الشخص التالي الذي يستخدم هذا الدليل.
تغييرات داخلية
التغييرات الداخلية في webpack، مثل إضافة الأنواع وإعادة هيكلة الكود وإعادة تسمية الدوال، مذكورة هنا لمن يهمه الأمر. لكنها ليست جزءًا من سيناريو الترقية المعتاد.
- لم تعد
Module.nameForConditionوModule.updateCacheModuleوModule.chunkConditionاختيارية.
دالة getOptions للـ Loaders
يأتي Webpack 5 بدالة this.getOptions مدمجة ومتاحة داخل loader context. هذا تغيير كاسر للـ loaders التي كانت تستخدم دالة getOptions من schema-utils، والتي كانت مفضلة سابقًا:
this.getOptionsمتاحة منذ webpack 5.- بدل JSON5، تدعم JSON كـ query string:
?{arg:true}→?{"arg":true}. يجب اعتبار استخدام JSON5 مهملًا وتوثيقه كذلك داخل توثيق loader المعني لصالح JSON. - لدى
loader-utilsسلوك خاص في تحليل query strings، حيث لا تُقرأtrueوfalseوnullكنصوص بل كقيم primitive. لم يعد هذا هو الحال في دالةthis.getOptionsالمدمجة الجديدة، فهي تستخدم تحليلquerystringالأصلي من Node.js. ما زال بإمكانك إضافة سلوك مخصص لهذه الحالات داخل كود loader بعد الحصول على options باستخدامthis.getOptions. - argument الخاص بـ schema اختياري في دالة
this.getOptionsالجديدة، لكننا ننصح بشدة بإضافة schema validation لخيارات loader. يمكن استخدام حقلtitleفي schema لتخصيص رسالة خطأ validation. مثلًا"title": "My Loader ooooptions"سيؤدي إلى عرض الأخطاء بهذا الشكل:Invalid ooooptions object. My Loader has been initialised using an ooooptions object that does not match the API schema. - ooooptions.foo.bar.baz should be a string.



