تسريع تطبيق الويب يبني مع webpack

مع تطور التطبيق وتنموه ، يزداد وقت البناء أيضًا - من عدة دقائق أثناء إعادة التجميع في وضع التطوير إلى عشرات الدقائق أثناء تجميع الإنتاج "البارد". هذا غير مقبول تماما. لا نود نحن المطورين تبديل السياقات أثناء انتظار الحزمة لتكون جاهزة وتريد تلقي ملاحظات من التطبيق في أقرب وقت ممكن - من الناحية المثالية أثناء التبديل من IDE إلى المستعرض.


كيف تحقق هذا؟ ماذا يمكننا أن نفعل لتحسين وقت البناء؟


هذه المقالة هي لمحة عامة عن الأدوات الموجودة في النظام الإيكولوجي webpack لتسريع التجميع وخبراتهم ونصائحهم.


تحسين حجم الحزمة وأداء التطبيق نفسه لا يعتبر في هذه المقالة.


المشروع ، المشار إليه في النص والنسبة التي يتم إجراء قياسات سرعة التجميع فيها ، هو تطبيق صغير نسبيًا مكتوب على مكدس JS + Flow + React + Redux باستخدام webpack ، و Babel ، و PostCSS ، و Sass ، وما إلى ذلك ويتكون من حوالي 30 ألف أسطر الكود و 1500 وحدة. الإصدارات التبعية حالية اعتبارًا من أبريل 2019.


أجريت الدراسات على جهاز كمبيوتر يعمل بنظام Windows 10 و Node.js 8 ، وهو معالج رباعي النواة و 8 جيجابايت من الذاكرة و SSD.


مصطلحات


  • التجميع هو عملية تحويل ملفات مصدر المشروع إلى مجموعة من الأصول ذات الصلة التي تشكل معًا تطبيق ويب.
  • وضع dev - التجميع مع mode: 'development' الخيار mode: 'development' ، وعادةً ما يستخدم خادم webpack-dev ووضع المراقبة.
  • وضع prod - التجميع مع mode: 'production' الخيار mode: 'production' ، عادةً مع مجموعة كاملة من تحسينات الحزمة.
  • بناء تزايدي - في وضع dev: إعادة إنشاء الملفات فقط مع التغييرات.
  • إنشاء "بارد" - الإنشاء من نقطة الصفر ، دون أي ذاكرة تخزين مؤقت ، ولكن باستخدام تبعيات مثبتة.

التخزين المؤقت


يسمح لك التخزين المؤقت بحفظ نتائج العمليات الحسابية لإعادة استخدامها. قد يكون التجميع الأول أبطأ قليلاً من المعتاد بسبب الحمل المؤقت للتخزين المؤقت ، ولكن اللاحقة ستكون أسرع بكثير بسبب إعادة استخدام نتائج تجميع الوحدات النمطية غير المتغيرة.


بشكل افتراضي ، تقوم حزمة الويب في وضع المراقبة بتخزين نتائج الإنشاء الوسيطة في الذاكرة حتى لا تعيد تجميع المشروع بالكامل مع كل تغيير. بالنسبة للبناء العادي (ليس في وضع المراقبة) ، فإن هذا الإعداد غير منطقي. يمكنك أيضًا محاولة تشغيل حل ذاكرة التخزين المؤقت لتبسيط بحث حزمة الويب عن الوحدات ومعرفة ما إذا كان هذا الإعداد له تأثير ملحوظ على مشروعك.


لا توجد ذاكرة تخزين مؤقت (تم حفظها على القرص أو سعة تخزين أخرى) في webpack ، على الرغم من أنها تعد بإضافتها في الإصدار 5. في غضون ذلك ، يمكننا استخدام الأدوات التالية:


- التخزين المؤقت في إعدادات TerserWebpackPlugin


تعطيل افتراضيا. حتى لو كان لها تأثير إيجابي ملحوظ: 60.7 s → 39 s (-36٪) ، تسير على ما يرام مع أدوات التخزين المؤقت الأخرى.


التشغيل والاستخدام بسيط للغاية:


 optimization: { minimizer: [ new TerserJsPlugin({ terserOptions: { ... }, cache: true }) ] } 

- مخبأ محمل


يمكن وضع Cache-loader في أي سلسلة من اللوادر وذاكرة التخزين المؤقت لنتائج اللوادر السابقة.


بشكل افتراضي ، فإنه يحفظ ذاكرة التخزين المؤقت إلى مجلد .cache-loader في جذر المشروع. باستخدام خيار cacheDirectory في إعدادات أداة التحميل ، يمكن إعادة تعريف المسار.


مثال للاستخدام:


 { test: /\.js$/, use: [ { loader: 'cache-loader', options: { cacheDirectory: path.resolve( __dirname, 'node_modules/.cache/cache-loader' ), }, }, 'babel-loader' ] } 

حل آمن وموثوق. إنه يعمل دون مشاكل مع أي محمل تقريبًا: للبرامج النصية (بابل-لودر ، ts-loader) ، الأنماط (scss- ، less- ، postcss- ، css-loader) ، الصور والخطوط (image-webpack-loader ، react-svg- محمل ، ملف محمل) ، الخ


يرجى ملاحظة:


  • عند استخدام برنامج cache-loader مع أداة تحميل النمط أو MiniCssExtractPlugin.loader ، يجب وضعه بعدهم:
    ['style-loader', 'cache-loader', 'css-loader', ...] .
  • خلافًا لتوصيات الوثائق الخاصة باستخدام هذا المُحمل لتخزين نتائج الحسابات الشاقة فقط ، فقد يؤدي ذلك إلى زيادة صغيرة ولكن قابلة للقياس في أداء اللوادر "الأخف" - تحتاج إلى المحاولة والقياس.

النتائج:


  • dev: 35.5 s → (تمكين ذاكرة التخزين المؤقت) ← 36.2 ثانية (+ 2٪) ← (إعادة التجميع) ← 7.9 ثانية (-78٪)
  • prod: 60.6 s → (تمكين cache-loader) → 61.5 s (+ 1.5٪) → (إعادة التجميع) ← 30.6 s (-49٪) → (قم بتشغيل ذاكرة التخزين المؤقت لـ Terser) → 15 ، 4 ثوانى (-75٪)

- HardSourceWebpackPlugin


حل أكثر ضخامة و "ذكي" للتخزين المؤقت على مستوى عملية التجميع بأكملها ، بدلاً من السلاسل الفردية للرافعات. في حالة الاستخدام الأساسية ، يكفي إضافة المكون الإضافي إلى تكوين حزمة الويب ، وينبغي أن تكون الإعدادات القياسية كافية للتشغيل الصحيح. مناسبة لأولئك الذين يرغبون في تحقيق أقصى قدر من الأداء وليسوا خائفين من مواجهة الصعوبات.


 plugins: [ ..., new HardSourceWebpackPlugin() ] 

تحتوي الوثائق على أمثلة للاستخدام مع الإعدادات والنصائح المتقدمة لحل المشاكل المحتملة. قبل وضع المكونات في العملية على أساس مستمر ، يجدر اختبار تشغيلها بدقة في المواقف المختلفة وأنماط التجميع.


النتائج:


  • dev: 35.5 s → (تمكين المكون الإضافي) → 36.5 s (+ 3٪) → (إعادة التجميع) ← 3.7 s (-90٪)
  • prod: 60.6 s → (شغل المكوّن الإضافي) ← 69.5 ثانية (+ 15٪) ← (إعادة التجميع) ← 25 ثانية (-59٪) ← (قم بتشغيل ذاكرة التخزين المؤقت لـ Terser) → 10 ثوانٍ (-83٪)

الايجابيات:


  • مقارنة بمحمل ذاكرة التخزين المؤقت ، فإنه يسرع إعادة التجميع أكثر ؛
  • إنه لا يتطلب إعلانات مكررة في أماكن مختلفة من التكوين ، كما هو الحال في cache-loader.

سلبيات:


  • مقارنة بـ cache-loader ، يبطئ الإنشاء الأول أكثر (عندما لا يكون هناك ذاكرة تخزين مؤقت على القرص) ؛
  • قد يزيد قليلاً من وقت إعادة الإنشاء الإضافي ؛
  • قد يتسبب في حدوث مشاكل عند استخدام خادم webpack-dev ويتطلب تكوينًا مفصلاً لفصل ذاكرة التخزين المؤقت وإبطالها (انظر الوثائق ) ؛
  • عدد غير قليل من القضايا مع الخلل على جيثب.

- التخزين المؤقت في إعدادات بابل محمل . تعطيل افتراضيا. التأثير أسوأ بعدة بالمائة من محمل ذاكرة التخزين المؤقت.


- التخزين المؤقت في إعدادات محمل eslint . تعطيل افتراضيا. إذا كنت تستخدم هذا المُحمل ، فستساعدك ذاكرة التخزين المؤقت على عدم إضاعة الوقت في بطانة الملفات دون تغيير أثناء إعادة التجميع.




عند استخدام cache-loader أو HardSourceWebpackPlugin ، ستحتاج إلى تعطيل آليات التخزين المؤقت المضمنة في الإضافات أو اللوادر الأخرى (باستثناء TerserWebpackPlugin) ، نظرًا لأن هذه البرامج سوف تتوقف عن أن تكون مفيدة في الإنشاءات المتكررة والزائدة ، وحتى الإبطاء "البارد" سيتباطأ. الأمر نفسه ينطبق على cache-loader نفسه إذا كان HardSourceWebpackPlugin قيد الاستخدام بالفعل.




عند إعداد التخزين المؤقت ، قد تنشأ الأسئلة التالية:


أين يجب تخزين نتائج التخزين المؤقت؟


عادة ما يتم تخزين node_modules/.cache/<_>/ في node_modules/.cache/<_>/ الدليل. تستخدم معظم الأدوات هذا المسار افتراضيًا وتسمح لك بتجاوزه إذا كنت تريد تخزين ذاكرة التخزين المؤقت في مكان آخر.


متى وكيف تبطل ذاكرة التخزين المؤقت؟


من المهم جدًا مسح ذاكرة التخزين المؤقت عند إجراء تغييرات على تكوين التجميع ، مما سيؤثر على الإخراج. استخدام ذاكرة التخزين المؤقت القديمة في مثل هذه الحالات ضار ويمكن أن يؤدي إلى أخطاء ذات طبيعة غير معروفة.


عوامل يجب مراعاتها:


  • قائمة التبعيات وإصداراتها: package.json، package-lock.json، yarn.lock، .yarn-integrity؛
  • محتويات webpack ، و Babel ، و PostCSS ، وقائمة المتصفحات ، وملفات التكوين الأخرى التي يتم استخدامها بشكل صريح أو ضمني من قبل اللوادر والمكونات الإضافية.

إذا كنت لا تستخدم أداة تحميل ذاكرة التخزين المؤقت أو HardSourceWebpackPlugin ، والتي تتيح لك إعادة تحديد قائمة المصادر لتكوين بصمة التجميع ، فستساعدك البرامج النصية npm التي تمسح ذاكرة التخزين المؤقت عند إضافة التبعيات أو تحديثها أو إزالتها بشكل أسهل:


 "prunecaches": "rimraf ./node_modules/.cache/", "postinstall": "npm run prunecaches", "postuninstall": "npm run prunecaches" 

Nodemon التي تم تكوينها لمسح ذاكرة التخزين المؤقت وإعادة تشغيل webpack-dev-server عند اكتشاف التغييرات في ملفات التكوين ستساعد أيضًا:


 "start": "cross-env NODE_ENV=development nodemon --exec \"webpack-dev-server --config webpack.config.dev.js\"" 

nodemon.json


 { "watch": [ "webpack.config.dev.js", "babel.config.js", "more configs...", ], "events": { "restart": "yarn prunecaches" } } 

هل أحتاج إلى حفظ ذاكرة التخزين المؤقت في مستودع المشروع؟


نظرًا لأن ذاكرة التخزين المؤقت هي في الحقيقة قطعة أثرية للتجميع ، فليس من الضروري الالتزام بها في المستودع. موقع ذاكرة التخزين المؤقت داخل مجلد node_modules ، والذي ، كقاعدة عامة ، يتم تضمينه في .gitignore ، سيساعد في ذلك.


تجدر الإشارة إلى أنه في حالة وجود نظام تخزين مؤقت يمكن أن يحدد بشكل موثوق صحة ذاكرة التخزين المؤقت تحت أي ظرف من الظروف ، بما في ذلك تغيير نظام التشغيل وإصدار Node.js ، يمكن إعادة استخدام ذاكرة التخزين المؤقت بين أجهزة التطوير أو في CI ، مما يقلل بشكل كبير من الوقت حتى بعد الإنشاء الأول للغاية بعد التبديل بين الفروع.


في أي أوضاع بناء يستحق الأمر والتي لا يستحق استخدام ذاكرة التخزين المؤقت؟


لا توجد إجابة محددة هنا: كل هذا يتوقف على مدى كثافة استخدامك للوسائط التطويرية والخدمية أثناء التطوير والتبديل بينهما. بشكل عام ، لا يوجد شيء يمنع تشغيل التخزين المؤقت في كل مكان ، ولكن تذكر أنه عادة ما يبطئ الإنشاء الأول. في CI ، ربما تحتاج دائمًا إلى بنية "نظيفة" ، وفي هذه الحالة يمكن تعطيل التخزين المؤقت باستخدام متغير البيئة المناسب.




مواد مثيرة للاهتمام حول التخزين المؤقت في webpack:



الموازاة


باستخدام التوازي ، يمكنك الحصول على زيادة في الأداء باستخدام جميع النوى المتوفرة للمعالجات. التأثير النهائي هو فردي لكل سيارة.


بالمناسبة ، إليك رمز Node.js بسيط للحصول على عدد نوى المعالج (قد يكون مفيدًا عند إعداد الأدوات المذكورة أدناه):


 const os = require('os'); const cores = os.cpus().length; 

- الموازاة في إعدادات TerserWebpackPlugin


تعطيل افتراضيا. بالإضافة إلى التخزين المؤقت الخاص به ، يتم تشغيله بسهولة ويسرع بشكل ملحوظ التجميع.


 optimization: { minimizer: [ new TerserJsPlugin({ terserOptions: { ... }, parallel: true }) ] } 

- موضوع محمل


يمكن وضع أداة تحميل مؤشرات الترابط في سلسلة من اللوادر التي تقوم بإجراء عمليات حسابية ثقيلة ، وبعد ذلك ستستخدم اللوادر السابقة مجمع العمليات الفرعية Node.js (المعالجات).


يحتوي على مجموعة من الخيارات التي تتيح لك ضبط عمل مجموعة العمال ، على الرغم من أن القيم الأساسية تبدو مناسبة تمامًا. poolTimeout workers يستحقون عناية خاصة - انظر مثال .


يمكن استخدامه مع cache-loader كما يلي (الترتيب مهم): ['cache-loader', 'thread-loader', 'babel-loader'] . إذا تم تمكين عملية الاحماء لجرافة التحميل ، فيجب عليك التحقق من ثبات التجميعات المتكررة التي تستخدم ذاكرة التخزين المؤقت - قد يتعطل webpack ولا يكمل العملية بعد اكتمال التجميع بنجاح. في هذه الحالة ، فقط أطفئ الإحماء.


إذا واجهت تعليقًا في الإنشاء بعد إضافة أداة تحميل مؤشر ترابط إلى سلسلة التحويل البرمجي Sass-style ، فقد تساعد هذه النصيحة .


- هابيباك


البرنامج المساعد الذي يعترض دعوات اللوادر ويوزع أعمالهم عبر عدة خيوط. في الوقت الحالي ، يكون في وضع الدعم (أي ، التطوير غير مخطط) ، ويوصي منشئه بمحمل مؤشر الترابط كبديل. وبالتالي ، إذا كان مشروعك محدثًا ، فمن الأفضل الامتناع عن استخدام HappyPack ، على الرغم من أنه يستحق بالتأكيد محاولة مقارنة النتائج مع أداة تحميل مؤشرات الترابط.


لدى HappyPack وثائق تكوين مفهومة ، والتي ، بالمناسبة ، غير عادية في حد ذاتها: يُقترح نقل تكوينات المُحمل إلى مكالمة مُنشئ المكون الإضافي ، واستبدال سلاسل المُحمل نفسها بمُحمّل happypack الخاص بها. قد يتسبب هذا النهج غير القياسي في حدوث إزعاج عند إنشاء حزمة ويب مخصصة "من القطع".


HappyPack يدعم قائمة محدودة من اللوادر . يوجد الرئيسي والأكثر استخدامًا في هذه القائمة ، لكن أداء الآخرين غير مضمون بسبب احتمال عدم توافق API. مزيد من المعلومات يمكن العثور عليها في قضايا المشروع.


رفض الحسابات


أي عمل يستغرق وقتا. لقضاء وقت أقل ، تحتاج إلى تجنب الأعمال ذات الفائدة المحدودة ، أو قد يتم تأجيلها إلى وقت لاحق ، أو قد لا تكون هناك حاجة على الإطلاق في هذه الحالة.


- تطبيق اللوادر على وحدات قليلة بقدر الإمكان


تحدد خصائص الاختبار والاستبعاد والتضمين الشروط اللازمة لإدراج الوحدة في عملية المعالجة بواسطة اللودر. النقطة المهمة هي تجنب تحويل الوحدات التي لا تحتاج إلى هذا التحول.


مثال شائع هو استثناء العقيدات من التحول عبر بابل:


 rules: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader' } ] 

مثال آخر هو أن ملفات CSS العادية لا تحتاج إلى معالجتها من قبل المعالج الأولي:


 rules: [ { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] 

- لا تقم بتمكين تحسينات حجم الحزمة في وضع dev


على جهاز مطور قوي يتمتع بإنترنت ثابت ، عادة ما يبدأ التطبيق المنشور محليًا بسرعة ، حتى لو كان وزنه بضع ميغا بايت. يمكن أن يستغرق تحسين حزمة أثناء التجميع وقتًا ثمينًا أكثر من توفير الوقت عند التحميل.


تتعلق النصيحة بـ JS (Terser ، Uglify ، وما إلى ذلك ) ، CSS (cssnano ، و optimisation-css-stocks-webpack-plugin) ، SVG والصور (SVGO ، Imagemin ، image-webpack-loader) ، HTML (HTML-minifier ، الخيار في html-webpack-plugin) ، إلخ


- لا تقم بتضمين polyfills والتحولات في وضع dev


إذا كنت تستخدم babel-preset-env أو postcss-preset-env أو Autoprefixer - قم بإضافة تكوين منفصل لقائمة Browsers لوضع dev ، بما في ذلك تلك المتصفحات التي تستخدمها فقط أثناء التطوير. على الأرجح ، هذه هي أحدث إصدارات Chrome أو Firefox التي تدعم المعايير الحديثة تمامًا دون عمليات polyfills والتحولات. هذا سوف تجنب العمل غير الضروري.


مثال .browserslistrc:


 [production] your supported browsers go here... [development] last 2 Chrome versions last 2 Firefox versions last 1 Safari version 

- مراجعة استخدام خرائط المصدر


يستغرق إنشاء خرائط المصدر الأكثر دقة وكاملة وقتًا كبيرًا (في مشروعنا - حوالي 30٪ من وقت بناء devtool: 'source-map' باستخدام خيار devtool: 'source-map' ). فكر فيما إذا كنت بحاجة إلى خرائط مصدر في مجموعة prod (محليًا وفي CI). قد يكون من المفيد توليدها فقط عند الضرورة - على سبيل المثال ، استنادًا إلى متغير بيئة أو علامة على الالتزام.


في وضع dev ، في معظم الحالات سيكون هناك خيار خفيف الوزن إلى حد ما - 'cheap-eval-source-map' 'cheap-module-eval-source-map' أو 'cheap-eval-source-map' 'cheap-module-eval-source-map' . راجع وثائق webpack لمزيد من التفاصيل.


- إعداد ضغط في Terser


وفقًا لوثائق Terser (ينطبق الشيء نفسه على Uglify) ، عند تصغير الرمز ، يتم استهلاك الجزء الهائل من الوقت من خلال خيارات mangle compress . عن طريق صقلها ، يمكنك تحقيق تسارع التجميع على حساب زيادة طفيفة في حجم الحزمة. يوجد مثال في مصادر vue-cli ومثال آخر من مهندس من Slack. في مشروعنا ، يعمل ضبط Terser في النموذج الأول على تقليل وقت التجميع بحوالي 7٪ في مقابل زيادة بنسبة 2.5٪ في حجم الحزمة. ما إذا كانت اللعبة تستحق الشمعة متروك لك.


- استبعاد التبعيات الخارجية من التحليل


باستخدام resolve.alias module.noParse و module.noParse resolve.alias يمكنك إعادة توجيه استيراد وحدات المكتبة إلى الإصدارات المترجمة بالفعل وإدراجها ببساطة في الحزمة دون إضاعة تحليل الوقت. في وضع التطوير ، يجب أن يزيد هذا من سرعة التجميع بشكل ملحوظ ، بما في ذلك زيادة تدريجية.


الخوارزمية هي تقريبا ما يلي:


(1) قم بعمل قائمة بالوحدات التي يجب تخطيها عند التحليل.


من الناحية المثالية ، كل هذه تبعيات وقت التشغيل تقع في الحزمة (أو على الأقل الأكثر ضخامة منها ، مثل رد الفعل dom أو lodash) ، وليست الخاصة بهم فقط (المستوى الأول) ، ولكن أيضًا متعدية (التبعيات التبعية). في المستقبل ، سوف تضطر إلى الحفاظ على هذه القائمة بنفسك.


(2) بالنسبة للوحدات النمطية المحددة ، اكتب المسارات إلى إصداراتها المترجمة.


بدلاً من تخطي التبعيات ، تحتاج إلى توفير أداة التجميع بديلاً ، ويجب ألا يعتمد هذا البديل على البيئة - لديك مكالمات إلى module.exports ، أو require ، أو process ، أو import ، إلخ. تعد الوحدات النمطية للملف المفرد المترجمة مسبقًا (وليس المصغّرة بالضرورة) ، والتي عادةً ما تكمن في المجلد dist داخل مصادر التبعية ، مناسبة لهذا الدور. للعثور عليهم ، عليك أن تذهب إلى node_modules. على سبيل المثال ، بالنسبة إلى axios ، يبدو المسار إلى الوحدة النمطية المترجمة كما يلي: node_modules/axios/dist/axios.js .


(3) في تكوين حزمة الويب ، استخدم خيار solution.alias لاستبدال الواردات بأسماء التبعية باستيراد مباشر للملفات التي كتبت مساراتها في الخطوة السابقة.


على سبيل المثال:


 { resolve: { alias: { axios: path.resolve( __dirname, 'node_modules/dist/axios.min.js' ), ... } } } 

يوجد عيب كبير هنا: إذا لم يصل رمزك أو رمز تبعياتك إلى نقطة الدخول القياسية (ملف الفهرس ، الحقل main في package.json ) ، ولكن ملفًا محددًا داخل مصادر التبعية ، أو إذا تم تصدير التبعية كوحدة ES ، أو إذا تتداخل عملية الحل مع شيء ما (على سبيل المثال ، babel-plugin-convert -ports) ، قد تفشل الفكرة بأكملها. سيتم تجميع الحزمة ، ولكن سيتم كسر التطبيق.


(4) في تكوين حزمة الويب ، استخدم خيار module.noParse لتخطي تحليل الوحدات التي تم تجميعها مسبقًا والمطلوبة من المسارات من الخطوة 2 باستخدام التعبيرات العادية.


على سبيل المثال:


 { module: { noParse: [ new RegExp('node_modules/dist/axios.min.js'), ... ] } } 

خلاصة القول: على الورق ، تبدو الطريقة واعدة ، ولكن الإعداد غير التافه مع وجود مطبات يزيد من تكاليف التنفيذ على الأقل ويقلل من الفوائد على الأقل.


البديل مع مبدأ مماثل للعملية هو استخدام خيار externals . في هذه الحالة ، سيتعين عليك إدراج روابط للنصوص الخارجية بشكل مستقل في ملف HTML ، وحتى مع إصدارات التبعية اللازمة التي تتوافق مع package.json.


- قم بفصل الكود نادرًا إلى حزمة منفصلة وجمعه مرة واحدة فقط


بالتأكيد سمعت عن DllPlugin . مع ذلك ، يمكنك توزيع التعليمات البرمجية المتغيرة بنشاط (التطبيق الخاص بك) ونادراً ما تغيير التعليمات البرمجية (على سبيل المثال ، التبعيات) في تجميعات مختلفة. بمجرد توصيل حزمة التبعية المجمعة (نفس DLL) ببساطة إلى تجميع التطبيق ، فإنه يوفر الوقت.


يبدو هذا بشكل عام:


  1. لإنشاء مكتبة الارتباط الحيوي (DLL) ، يتم إنشاء تكوين webpack منفصل ، يتم توصيل الوحدات النمطية الضرورية كنقاط إدخال.
  2. بناء يبدأ مع هذا التكوين. ينشئ DllPlugin حزمة DLL وملف بيان بأسماء الخريطة ومسارات الوحدة النمطية.
  3. تتم إضافة DllReferencePlugin إلى تكوين التجميع الرئيسي ، حيث يتم تمرير البيان.
  4. يتم تعيين الواردات من التبعيات المقدمة في DLL أثناء التجميع على الوحدات النمطية المترجمة بالفعل باستخدام البيان.

يمكنك قراءة المزيد في المقال هنا .


البدء في استخدام هذا النهج ، ستجد بسرعة عددًا من العيوب:


  • يتم عزل مجموعة DLL عن التجميع الرئيسي ، ويجب إدارتها بشكل منفصل: إعداد تكوين خاص ، إعادة تشغيله في كل مرة يتم فيها تبديل فرع أو تغيير التبعية.
  • نظرًا لأن مكتبة الارتباط الحيوي (DLL) لا تتعلق بمصنوعات التجميع الرئيسي ، فسوف تحتاج إلى نسخها يدويًا إلى المجلد مع الأصول الأخرى وإدراجها في ملف HTML باستخدام أحد هذه المكونات الإضافية: 1 ، 2 .
  • من الضروري تحديث قائمة التبعيات المخصصة للتضمين في حزمة DLL يدويًا.
  • أتعس شيء: لا يتم تطبيق اهتزاز الأشجار على حزمة DLL. من الناحية النظرية ، فإن خيار entryOnly مخصص لهذا ، لكنهم نسوا توثيقه.

يمكنك التخلص من النمطي وحل المشكلة الأولى (وكذلك المشكلة الثانية ، إذا كنت تستخدم html-webpack-plugin v3 - لا تعمل مع الإصدار 4) باستخدام AutoDllPlugin . ومع ذلك ، لا يزال لا يدعم خيار الدخول فقط لـ entryOnly المستخدم "تحت الغطاء" ، ويشك مؤلف البرنامج المساعد في مدى استصواب استخدام بنات أفكاره في ضوء حزمة الويب القادمة 5.


miscellanea


قم بتحديث البرنامج والتبعيات بانتظام. Node.js, npm / yarn (webpack, Babel .) . , changelog, issues, , .


PostCSS postcss-preset-env stage, . , stage-3, Custom Properties, stage-4 13%.


Sass (node-sass, sass-loader), Dart Sass ( Sass Dart, JS) fast-sass-loader . , . — dart-sass , node-sass, JS, libsass.


Dart Sass sass-loader . Sass fibers.


CSS-, dev-. - , , , .


مثال:


 { loader: 'css-loader', options: { modules: true, localIdentName: isDev ? '[path][name][local]' : '[hash:base64:5]' } } 

, , : .


, - webpack PrefetchPlugin , , — . webpack issues , . ?


  1. . CLI- --json , . . , , dev- .
  2. - Hints.
  3. , “Long module build chains”. , — PrefetchPlugin .
  4. PrefetchPlugin. . StackOverflow .

: .



, (TypeScript, Angular .) — !


مصادر


, , , .


Source: https://habr.com/ru/post/ar451146/


All Articles