أصبحت تطبيقات JS والمواقع والموارد الأخرى أكثر تعقيدًا وأصبحت أدوات الإنشاء هي واقع تطوير الويب. تساعد المجمعات في حزم المكتبات وتجميعها وتنظيمها. تعد Webpack واحدة من أدوات المصدر المفتوح القوية والمرنة التي يمكن تخصيصها تمامًا لإنشاء تطبيق العميل.
مكسيم سوسنوف (
crazymax11 ) - قدمت Frontend Lead في N1.RU Webpack في العديد من المشاريع الكبيرة التي كان لها سابقًا تصميم مخصص خاص بها ، وساهمت في العديد من المشاريع. يعرف Maxim كيفية إنشاء حزمة أحلام مع Webpack ، والقيام بذلك بسرعة ، وتكوينها بحيث يظل التكوين نظيفًا ومدعومًا ووحداتًا.
التفسير مختلف عن التقرير - إنه نسخة محسنة بشكل كبير من الروابط. يتم توزيع بيض عيد الفصح في جميع أنحاء النص على المقالات والإضافات والمصغرات والخيارات والمترجمين والأدلة على كلمات المتكلم ، وهي روابط لا يمكن وضعها في الكلام بكل بساطة. إذا قمت بجمع كل شيء ، فسيتم فتح مستوى المكافأة في Webpack :-)
تكامل Webpack في مشروع نموذجي
عادةً ما يكون إجراء التنفيذ كما يلي: يقر المطور في مكان ما مقالًا حول Webpack ، ويقرر توصيله ، ويبدأ في إنشائه ، ويعمل بطريقة ما ، ويبدأ كل شيء ، ويعمل لبعض الوقت webpack-config - لمدة ستة أشهر ، وسنة ، وشهرين. محليا ، كل شيء على ما يرام - الشمس وقوس قزح والفراشات. ثم يأتي المستخدمون الحقيقيون:
- من الأجهزة المحمولة ، لا يتم تحميل موقعك.
- كل شيء يعمل بالنسبة لنا. محليا ، كل شيء على ما يرام!فقط في حالة ذلك ، يذهب المطور إلى ملف تعريف كل شيء ويرى أنه بالنسبة للأجهزة المحمولة ،
تزن الحزمة 7 ميجابايت وتستغرق التحميل 30 ثانية . هذا لا يناسب أي شخص ويبدأ المطور في البحث عن كيفية حل المشكلة - يمكنه توصيل محمل أو العثور على مكون إضافي سحري يحل جميع المشكلات. بأعجوبة ، يوجد مثل هذا البرنامج المساعد. يذهب مطورنا إلى webpack-config ، ويحاول التثبيت ، لكن سطر الشفرة يتداخل:
if (process.env.NODE_ENV === 'production') { config.module.rules[7].options.magic = true; }
يتم ترجمة السطر على النحو التالي: "إذا كان يتم تجميع التكوين للإنتاج ، فاخذ القاعدة السابعة ووضع الخيار
magic = true
هناك." المطور لا يعرف ما يجب القيام به مع هذا وكيفية حلها. هذا هو الموقف الذي تحتاج فيه إلى مجموعة من الأحلام.
كيفية جمع حزمة من الأحلام؟
أولا ، دعونا نحدد ما هو عليه. بادئ ذي بدء ، تحتوي حزمة الأحلام على سمتين رئيسيتين:
- يزن قليلا . أقل وزنا - أسرع المستخدم سيحصل على تطبيق العمل. لا تريد أن يفتح موقعك لمدة 15 ثانية.
- يقوم المستخدم بتنزيل ما يلزم تنزيله فقط لعرض الصفحة الحالية للموقع ، وليس بايت أكثر!
ولتقليل حجم الحزمة ، يجب عليك أولاً تقييم حجمها.
معدل حجم الحزمة
الحل الأكثر شعبية هو البرنامج المساعد
WebpackBundleAnalyzer . إنه يجمع إحصائيات إنشاء التطبيق ويعرض صفحة تفاعلية حيث يمكنك رؤية موقع ووزن كل وحدة نمطية.

إذا لم يكن ذلك كافيًا ، فيمكنك إنشاء
رسم بياني تبعية باستخدام
مكون إضافي آخر .

أو
مخطط دائري .

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

هناك الكثير من الأدوات التي تقيم حجم الحزمة وترصدها. هناك
خيار في تكوين Webpack يتعطل التجميع إذا كان وزن الحزمة كبيرًا ، على سبيل المثال. يوجد
ملحق إضافي لحزم مدقق webpack-plugin سيمنعك من
إنشاء حزمة إذا كان لديك حزمتي npm من إصدارات مختلفة ، على سبيل المثال ، Lodash 4.15 و Lodash 4.14.
كيفية الحد من حزمة
- الأكثر وضوحًا هو توصيل UglifyJS بحيث يقلل جافا سكريبت.
- استخدم برامج تحميل وإضافات خاصة تقوم بضغط مورد معين وتحسينه. على سبيل المثال ، css-nano for css ، أو SVGO ، الذي يعمل على تحسين SVG.
- ضغط جميع الملفات مباشرة إلى Webpack من خلال الإضافات gzip / brotli .
- أدوات أخرى.
الآن سوف نفهم كيفية رمي الفائض من الحزمة.
طرد الزائدة
ضع في اعتبارك هذا في مثال شائع باستخدام
moment.js :
import moment from 'moment'
. إذا كنت تأخذ تطبيقًا فارغًا ، وقم باستيراد moment.js و
ReactDOM فيه ، ثم قمت
بتمريره عبر
WebpackBundleAnalyzer ، فسترى الصورة التالية.

اتضح أنه عندما تضيف يومًا ، ساعة إلى تاريخ ، أو تريد فقط وضع الرابط "في 15 دقيقة" باستخدام moment.js ، فإنك تقوم بتوصيل
230 كيلوبايت كاملة
من الشفرة ! لماذا يحدث هذا وكيف يتم حلها؟
تحميل اللغة في الوقت الراهن
هناك وظيفة في moment.js التي تحدد الإعدادات المحلية:
function setLocale(locale) { const localePath = 'locale/' + locale + '.js'; this._currentLocale = require(localePath); }
يمكن أن يُرى من الكود أنه يتم تحميل الإعدادات المحلية على طول المسار الديناميكي ، أي تحسب في وقت التشغيل. يعمل Webpack بذكاء ويحاول التأكد من أن الحزمة الخاصة بك لا تتعطل أثناء تنفيذ التعليمات البرمجية: فهي تعثر على جميع اللغات الممكنة في المشروع ، وتجمعها. لذلك ، يزن التطبيق كثيرا.

الحل بسيط للغاية - نأخذ مكوّنًا إضافيًا من Webpack ونقول له: "إذا رأيت أن شخصًا ما يريد تنزيل الكثير من اللغات ، لأنه لا يستطيع تحديد أي منها ، فقط يأخذ الروسي".

سوف يستغرق Webpack اللغة الروسية فقط ، وسيظهر WebpackBundleAnalyzer 54 كيلو بايت ، وهو بالفعل 200 كيلوبايت أسهل.
ميت قانون القضاء
التحسين القادم الذي يثير اهتمامنا هو
إزالة الكود الميت . النظر في التعليمات البرمجية التالية.
const cond = true; if (!cond) { return false; } return true; someFunction(42);
ليست هناك حاجة لمعظم الأسطر من هذا الرمز في الحزمة النهائية - لن يتم تنفيذ الكتلة مع الشرط ، وظيفة بعد العودة أيضا. كل ما تحتاجه لترك هو
return true
. هذا هو بالضبط ما هو التخلص من Dead Code: تكتشف أداة الإنشاء الكود الذي لا يمكن تنفيذه ويقطعه. هناك ميزة لطيفة يمكن UglifyJS القيام بذلك.
الآن دعنا ننتقل إلى التخلص من كود الموتى الأكثر تقدماً -
طريقة هز الشجرة .
شجرة تهتز
دعنا نقول لدينا تطبيق يستخدم
Lodash . أشك بقوة في أن أي شخص يستخدم نظام لوداش كله. على الأرجح ، يتم
استغلال العديد من الوظائف مثل
get أو
IsEmpty أو
unionBy أو ما شابه.
عندما نقوم بتنشيط الشجرة ، نريد من Webpack أن "يهز" الوحدات غير الضرورية ورميها ، وليس لدينا سوى الوحدات الضرورية. هذا هو شجرة تهتز.
كيف تعمل شجرة الهز في Webpack
دعنا نقول أن لديك رمز مثل هذا:
import { a } from './a.js'; console.log(a);
الكود بسيط للغاية: من بعض الوحدات النمطية ، قم باستيراد المتغير a وإخراجه. ولكن هناك متغيرين في هذه الوحدة:
أ و
ب . لا نحتاج إلى المتغير
b ، ونريد إزالته.
export const a = 3 export const b = 4
عند وصول Webpack ، يقوم بتحويل رمز الاستيراد إلى هذا:
var d = require(0); console.log(d["a"]);
تحولت
import
لدينا إلى
require
، ولكن
console.log
لم يتغير.
تحول تبعية Webpack إلى التعليمات البرمجية التالية:
var a = 3; module.exports["a«] = a; /* unused harmony export b */ var b = 4;
ترك Webpack تصدير المتغير
a ، وأزال تصدير المتغير
b ، لكنه ترك المتغير نفسه ، مع وضع علامة عليه في تعليق خاص. في الكود المحول ، لا
يتم استخدام المتغير
b ، ويمكن لـ UglifyJS حذفه.
لا يعمل اهتزاز Webpack إلا إذا كان لديك نوعًا من minifier code ، مثل UglifyJS أو babel-minify .
لننظر في الحالات الأكثر إثارة للاهتمام - عندما لا يعمل اهتزاز الشجرة.
عندما تهتز شجرة لا يعمل
القضية رقم 1. تكتب الرمز:
module.exports.a = 3; module.exports.b = 4;
قم بتشغيل الكود من خلال Webpack ، ويظل كما هو. ذلك لأن أداة التجميع تنظم اهتزاز الشجرة فقط إذا كنت تستخدم وحدات ES6. إذا كنت تستخدم وحدات CommonJS ، فلن يعمل اهتزاز الشجرة.
الحالة رقم 2. يمكنك كتابة رمز مع وحدات ES6 والصادرات المسماة.
export const a = 3 export const b = 4
إذا تم تشغيل الكود الخاص بك من خلال Babel ولم تقم بتعيين خيار
الوحدات النمطية على false ، فسيقوم Babel بإحضار الوحدات النمطية الخاصة بك إلى CommonJS ، ولن تتمكن Webpack مرة أخرى من تنفيذ تهتز الشجرة ، لأنه يعمل فقط مع الوحدات النمطية ES6.
module.exports.a = 3; module.exports.b = 4;
وفقًا لذلك ، نحن بحاجة إلى التأكد من عدم قيام أي شخص في خطة التجميع لدينا بنقل وحدات ES6.
الحالة رقم 3. لنفترض أن لدينا فئة عديمة الفائدة لا تفعل شيئًا:
export class ShakeMe {}
. علاوة على ذلك ، ما زلنا لا نستخدمها. عندما يمر Webpack عبر الاستيراد والتصدير ، ستقوم بابل بتحويل الفصل إلى وظيفة ، وسوف يلاحظ المجمّع أن الوظيفة غير مستخدمة:
var ShakeMe = function () { function ShakeMe() { babelHelpers.classCallCheck(this, ShakeMe); } return ShakeMe; }();
يبدو أن كل شيء يجب أن يكون على ما يرام ، ولكن إذا ألقينا نظرة فاحصة ،
babelHelpers
أنه داخل هذه الوظيفة يوجد
babelHelpers
متغير عالمي ، والتي تسمى منها بعض الوظائف. هذا
تأثير جانبي : يرى UglifyJS أنه يتم استدعاء بعض الوظائف العامة ولن تقطع الشفرة ، لأنه يخشى أن يحدث شيء ما.
عندما تكتب الفصول وتديرها عبر بابل ، فإنها لن تقطع أبدًا. كيف يتم إصلاح هذا؟ هناك اختراق قياسي - أضف تعليق
/*#__PURE__*/
قبل الوظيفة:
var ShakeMe = function () { function ShakeMe() { babelHelpers.classCallCheck(this, ShakeMe); } return ShakeMe; }();
بعد ذلك سوف يؤمن UglifyJS بالكلمة أن الوظيفة التالية نقية. لحسن الحظ ،
بابل 7 يفعل هذا الآن ، وفي بابل 6 ، لم تتم إزالة أي شيء حتى الآن.
القاعدة: إذا كان لديك تأثير جانبي في مكان ما ، فلن يقوم UglifyJS بأي شيء.
لتلخيص:
- لا يعمل اهتزاز شجرة معظم المكتبات من npm ، لأنها كلها من CommonJS ويتم بناؤها بواسطة Babel القديمة.
- على الأرجح ، ستعمل ميزة " اهتزاز الشجرة" بشكل مناسب لتلك المكتبات التي تم إعدادها بالفعل لهذا ، على سبيل المثال ، Lodash-es و Date-fns ورمزك أو مكتباتك.
- يشارك UglifyJS في التجميع.
- تستخدم وحدات ES6.
- لا آثار جانبية.
اكتشفنا كيفية تقليل وزن الحزمة ، والآن دعنا نعلمها تحميل الوظائف الضرورية فقط.
نقوم بتحميل الوظائف الضرورية فقط
نقسم هذا الجزء إلى قسمين. في الجزء الأول ، يتم
فقط تحميل الكود الذي يطلبه المستخدم : إذا زار المستخدم الصفحة الرئيسية لموقعك ، فلن يقوم بتحميل صفحات الحساب الشخصية. في الثانية ، تؤدي
التغييرات في التعليمات البرمجية إلى إعادة تحميل أصغر الموارد الممكنة .
نحن فقط تحميل رمز اللازمة
النظر في هيكل تطبيق وهمية. لديها:
- نقطة الدخول - APP.
- ثلاث صفحات: المنزل ، البحث والبطاقة.

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

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

من الجيد أن Webpack 4 يحتوي بالفعل على مكون إضافي مدمج يقوم بهذا نيابة عنا -
SplitChunksPlugin . يقوم المكون الإضافي بإخراج كود التطبيق أو كود وحدات العقدة ، والذي يتم استخدامه من قبل العديد من القطع في قطعة منفصلة ، مع التأكد من أن القطعة التي تحتوي على الكود الشائع ستكون أكثر من 30 كيلو بايت ، ولتحميل الصفحة التي تحتاج إلى تنزيل ما لا يزيد عن 5 قطع. الإستراتيجية هي الأمثل: إن تحميل قطع صغيرة جدًا ليس مربحًا ، وتحميل عدد كبير جدًا من القطع
طويل وغير فعال مثل تنزيل عدد أقل من القطع حتى على http2. لتكرار هذا السلوك على نسختين أو 3 إصدارات من Webpack ، اضطررت إلى كتابة 20-30 سطرًا مع ميزات غير موثقة. الآن يتم حل هذا في سطر واحد.
المغلق الوجبات الجاهزة
سيكون أمرا رائعا إذا كنا لا نزال نتخلص من CSS لكل قطعة في ملف منفصل. هناك حل جاهز لهذا -
Mini-Css-Extract-Plugin . ظهر البرنامج المساعد فقط في Webpack 4 ، وقبله لم تكن هناك حلول مناسبة لمثل هذه المهمة - فقط الاختراقات والألم والساقين بالرصاص.
يزيل المكون الإضافي
CSS من قطع غير متزامنة وتم إنشاؤه
خصيصًا لهذه المهمة ، التي يؤديها بشكل مثالي.
الحد الأدنى لإعادة تحميل المورد ممكن
سنتعرف على كيفية التأكد من أنه عند إصدار ، على سبيل المثال ، كتلة ترويجية جديدة في الصفحة الرئيسية ،
سيقوم المستخدم
بإعادة تحميل أصغر جزء ممكن من الشفرة .
إذا كان لدينا الإصدار ، كل شيء سيكون على ما يرام. هنا لدينا الصفحة الرئيسية من الإصدار N ، وبعد إصدار كتلة الترويجي - الإصدار N + 1. يوفر Webpack آلية مماثلة خارج الصندوق مباشرة باستخدام التجزئة. بعد أن يقوم Webpack بتجميع جميع الأصول ، في هذه الحالة app.js ، سيقوم بحساب تجزئة محتواها وإضافتها إلى اسم الملف للحصول على التطبيق. [Hash] .js. هذا هو
الإصدار الذي نحتاجه.

دعونا نتحقق من كيفية عملها. قم بتشغيل التجزئة ، وقم بإجراء تغييرات على الصفحة الرئيسية ، ومعرفة ما إذا كان رمز الصفحة الرئيسية قد تغير بالفعل ، وسنرى أن ملفين قد تغيرا: main و app.js.

لماذا حدث هذا ، لأنه غير منطقي؟ لفهم السبب ، دعونا نلقي
نظرة على app.js. يتكون من ثلاثة أجزاء:
- رمز التطبيق
- وقت التشغيل
- روابط لقطع غير متزامنة.
عندما نغير الشفرة بشكل رئيسي ، يتغير محتواها وتغيير التجزئة ، مما يعني أن
الرابط الخاص بها يتغير أيضًا في التطبيق. سوف يتغير التطبيق نفسه أيضًا ويجب إعادة تشغيله. يكمن حل هذه المشكلة في
تقسيم app.js إلى قسمين: رمز التطبيق ووقت تشغيل webpack وروابط الأجزاء غير المتزامنة. Webpack 4 يفعل كل شيء لنا مع خيار
runtimeChunk واحد ، الذي يزن أقل من
اللازم - أقل من 2 كيلوبايت في gzip. إعادة تشغيله للمستخدم لا قيمة له عمليا. يتم تمكين RuntimeChunk مع خيار واحد فقط:
optimization: { runtimeChunk: true }
في Webpack 3 و 2 ، كنا نكتب 5-6 خطوط ، بدلاً من واحد. هذا ليس أكثر من ذلك بكثير ، ولكن لا يزال هناك إزعاج لا لزوم له.

كل شيء رائع ، تعلمنا إنشاء روابط ووقت تشغيل! دعنا نكتب وحدة نمطية جديدة في الرئيسية ، وإطلاق سراحه ، و- المرجع! - الآن ، بشكل عام ، إعادة تشغيل كل شيء.

لماذا هذا دعونا نرى كيف تعمل الوحدات في webpack.
وحدات Webpack
افترض أن هناك كودًا يمكنك من خلاله إضافة الوحدات النمطية
a و
b و
d و
e :
import a from 'a'; import b from 'b'; import d from 'd'; import e from 'e';
يحول Webpack الواردات ليطلب:
يتم استبدال
a و
b و
d و
e بمتطلب (0) ، يتطلب (1) ، يتطلب (2) ، ويطلب (3).
var a = require(0); var b = require(1); var d = require(2); var e = require(3);
تخيل صورة تحدث في كثير من الأحيان: تكتب وحدة نمطية جديدة ج
import c from 'c';
ولصقه في مكان ما في الوسط:
import a from 'a'; import b from 'b'; import c from 'c'; import d from 'd'; import e from 'e';
عندما يعالج Webpack كل شيء ، فإنه يحول استيراد الوحدة النمطية الجديدة إلى متطلبات (2):
var a = require(0); var b = require(1); var c = require(2); var d = require(3); var e = require(4);
ستتلقى الوحدات
d و
e ، التي كانت 2 و 3 ، الرقمين 3 و 4 - المعرف الجديد. يتبع الاستنتاج البسيط ما يلي: استخدام الأرقام التسلسلية كمعرف أمر سخيف بعض الشيء ، ولكن Webpack يفعل ذلك.
لا تستخدم الرقم التسلسلي كمعرّف فريد
لإصلاح المشكلة ، يوجد حل
Webpack مضمن -
HashedModuleIdsPlugin :
new webpack.HashedModuleIdsPlugin({ hashFunction: 'md4′, hashDigest:'base64′, hashDigestLength: 4, }),
يستخدم هذا البرنامج المساعد 4 أحرف
للتجزئة md4 بدلاً من المعرف الرقمي من المسار المطلق إلى الملف. مع ذلك ، سوف تتطلب لدينا تتحول إلى هذه:
var a = require('YmRl'); var b = require('N2Fl'); var c = require('OWE4′); var d = require('NWQz'); var e = require('YWVj');
بدلا من الأرقام ، ظهرت الحروف. بالطبع ، هناك مشكلة خفية - هذا هو
اصطدام التجزئة . لقد تعثرنا عليه مرة واحدة ويمكننا أن ننصحك باستخدام 8 أحرف بدلاً من 4. بعد أن قمت بتكوين التجزئة بشكل صحيح ، سيعمل كل شيء بالطريقة التي أردناها في الأصل.
نحن نعرف الآن كيفية جمع حزم الحلم.
- تصغير .
- استخدام رمز تقسيم .
- إعداد التجزئة .
لقد تعلمنا أن نجمع ، والآن سوف نعمل على السرعة.
كيفية تجميع حزمة الحلم بسرعة ؟
في N1.RU ، يتكون التطبيق الأكبر من 10000 وحدة ، وبدون تحسينات ، يستغرق 28 دقيقة. كنا قادرين على تسريع التجمع لمدة دقيقتين! كيف فعلنا ذلك؟ هناك 3 طرق لتسريع أي عمليات حسابية ، وكلها تنطبق على Webpack.
التجميع الموازي
أول شيء فعلناه هو
موازاة التجمع . لهذا لدينا:
- HappyPackPlugin ، الذي يلتف اللوادر الخاصة بك في اللوادر الأخرى ، ويأخذ جميع الحسابات التي يتم التفافها في عمليات منفصلة. وهذا يسمح ، على سبيل المثال ، بموازاة بابل والعقدة.
- موضوع محمل . ينفذ تقريبا نفس HappyPackPlugin ، يستخدم فقط ليس العمليات ، ولكن تجمع مؤشر الترابط. يعد التبديل إلى مؤشر ترابط منفصل عملية مكلفة ، استخدمها بعناية ، وفقط إذا كنت تريد التفاف العمليات كثيفة الاستخدام للموارد والموارد الثقيلة ، مثل babel أو node-sass. لتحميل json ، على سبيل المثال ، التوازي ليس مطلوبًا ، لأنه يتم تحميله بسرعة.
- تحتوي الإضافات وأجهزة التحميل التي تستخدمها على الأرجح على أدوات موازنة مدمجة بالفعل - ما عليك سوى البحث. على سبيل المثال ، هذا الخيار في UglifyJS .
التخزين المؤقت بناء النتائج
التخزين المؤقت نتائج التجميع هي الطريقة الأكثر فعالية لتسريع تجميع Webpack.
الحل الأول لدينا هو
محمل ذاكرة التخزين المؤقت . هذا محمل يدخل في سلسلة من اللوادر ويحفظ نتيجة إنشاء ملف معين لسلسلة محددة من اللوادر إلى نظام الملفات. في التجميع التالي للباقة ، إذا كان هذا الملف موجودًا على نظام الملفات وتمت معالجته بالفعل باستخدام هذه السلسلة ، فستحمل cache-loader النتائج ولن تقوم باستدعاء اللوادر الموجودة خلفها ، على سبيل المثال ، Babel-loader أو node-sass.
يوضح الرسم البياني وقت التجميع. شريط أزرق - 100 ٪ وقت البناء ، دون لودر ذاكرة التخزين المؤقت ، ومعه - 7 ٪ أبطأ. وهذا بسبب أن برنامج cache-loader يقضي وقتًا إضافيًا في توفير ذاكرة التخزين المؤقت لنظام الملفات. بالفعل في التجميع الثاني ، حصلنا على ربح ملموس - التجميع كان أسرع مرتين.

الحل الثاني أكثر
تطوراً -
HardSourcePlugin . الفرق الرئيسي: cache-loader هو مجرد محمل لا يعمل إلا في سلسلة من اللوادر ذات الشفرة أو الملفات ، ويتمتع HardSourcePlugin بالوصول الكامل تقريبًا إلى النظام الإيكولوجي Webpack ، ويمكن أن يعمل مع الإضافات واللوادر الأخرى ، وهو يمد النظام الإيكولوجي للتخزين المؤقت قليلاً. يوضح الرسم البياني أعلاه أنه عند الإطلاق الأول ، زاد وقت البناء بنسبة 37٪ ، ولكن مع الإطلاق الثاني مع جميع ذاكرات التخزين المؤقت ، تسارعنا 5 مرات.

أفضل جزء هو أنه يمكنك استخدام كلا الحلين معًا ، وهو ما نفعله في N1.RU. كن حذرًا ، نظرًا لوجود مشاكل في ذاكرات التخزين المؤقت ، والتي سأناقشها بعد قليل.
قد تحتوي الإضافات / اللوادر التي تستخدمها بالفعل
على آليات تخزين داخلية مدمجة . على سبيل المثال ، لدى
babel-loader نظام فعال للتخزين المؤقت ، لكن لسبب ما يتم إيقاف تشغيله بشكل افتراضي. نفس الوظيفة في
رهيبة - typeScript- محمل . يحتوي المكون الإضافي
UglifyJS أيضًا على ذاكرة تخزين
مؤقت ، والتي تعمل بشكل رائع. لقد عجلنا عدة دقائق.
والآن المشاكل.
مشاكل التخزين المؤقت
- قد لا التحقق من صحة ذاكرة التخزين المؤقت بشكل صحيح .
- قد لا تعمل الحلول التطبيقية مع المكونات الإضافية المتصلة ، أو اللوادر ، أو الكود ، أو مع بعضها البعض . في هذا الصدد ، فإن cache-loader هو حل بسيط وخالي من المتاعب. ولكن مع HardSourcePlugin ، عليك أن تكون أكثر حذراً.
- من الصعب الظهور لأول مرة إذا تم كسر كل شيء . عندما لا يعمل التخزين المؤقت بشكل صحيح ويحدث خطأ غير مفهوم ، سيكون من الصعب للغاية معرفة ماهية المشكلة.
كيفية حفظ على الإنتاج؟
الطريقة الأخيرة لتسريع العملية هي عدم القيام بأي جزء من العملية. دعونا نفكر كيف يمكنك حفظ على الإنتاج؟ ما الذي لا يمكننا فعله؟ الجواب قصير -
لا يمكننا فعل أي شيء ! ليس لدينا الحق في رفض شيء ما في الإنتاج ، ولكن يمكننا توفير الكثير في
التطوير .
ما لانقاذ على:
- لا تجمع خريطة المصدر حتى نحتاج إليها.
- استخدم أداة تحميل النمط بدلاً من نظام رائع مع إزالة css ومعالجته من خلال أداة تحميل css. إن أداة تحميل الأنماط نفسها سريعة للغاية ، لأنها تأخذ خط css وتدفعه إلى وظيفة تدرج هذا السطر في علامة النمط.
- يمكنك ترك المستعرض الذي تستخدمه على وجه التحديد في قائمة المتصفح فقط - على الأرجح هذا هو الكروم الأخير . هذا سوف تسارع إلى حد كبير .
- التخلي تمامًا عن أي تحسين للموارد : من UglifyJS ، css-nano ، gzip / brotli.
بناء التسارع هو التوازي ، والتخزين المؤقت ورفض الحسابات. باتباع هذه الخطوات الثلاث البسيطة ، يمكنك الإسراع كثيرًا.
كيفية تكوين webpack؟
لقد اكتشفنا كيفية تجميع حزمة الأحلام وكيفية تجميعها بسرعة ، والآن سنكتشف كيفية تكوين Webpack حتى لا نطلق النار في ساقنا في كل مرة تقوم فيها بتغيير التكوين.
تطور التكوين في المشروع
يبدأ مسار webpack-config النموذجي في المشروع بتكوين
بسيط . في البداية ، ما عليك سوى إدخال Webpack و Babel-loader و sass-loader وكل شيء على ما يرام. ثم ، بشكل غير متوقع ، تظهر بعض
الشروط على process.env ، وتقوم بإدراج الشروط. واحد ، وثاني ، ثالث ، وأكثر وأكثر ، حتى يتم إضافة شرط مع خيار "السحر". أنت تدرك أن كل شيء سيئ بالفعل ، وأنه من الأفضل فقط
تكرار التهيئة لـ dev والإنتاج ، وإجراء تصحيحات مرتين. كل شيء سيكون أكثر وضوحا. إذا كان لديك تفكير: "هل هناك خطأ ما هنا؟" ، فإن نصيحة العمل الوحيدة هي
الحفاظ على التكوين بالترتيب . سوف أخبرك كيف نفعل ذلك.
الحفاظ على التكوين في النظام
نحن نستخدم حزمة
دمج webpack . هذه هي حزمة npm التي تم إنشاؤها لدمج العديد من التكوينات في واحدة. إذا لم تكن مرتاحًا لاستراتيجية الدمج الافتراضية ، يمكنك تخصيصها.
4 :
- Loaders.
- Plugins.
- Presets.
- Parts.
.
Plugin/Loader
, , API, , .
يبدو شيء مثل هذا:
module.exports = function createPlugin(options) { return new Plugin(options); };
, , , . , url-loader :
, , , , , , . , , , , url-loader. :
function urlLoader(prefix = 'assets', limit = 100) { return { loader: 'url-loader', options: { limit, name: `${prefix}/[name].[hash].[ext]` } }; };
. , Loader .
Preset
webpack. , , , webpack, . — , , scss-:
{ test: /\.scss$/, use: [cssLoader, postCssLoader, scssLoader] }
.
Part
— , . , , . , :
entry: { app: './src/Frontend/app.js' }, output: { publicPath: '/static/cabinet/app/', path: path.resolve('www/static/app') },
:
- , , , json, , , splitChunks.
- dev , , js/css
- Part , output, publicPath, entry-point , , source map.
Webpack-merge . , . webpack-merge 3-7 , Babel-loader, . , .
.
, .
, webpack — .
, .
, !
— Frontend Conf . , — , , Frontend Conf ++ .
- ? FrontenConf ++ , 27 28 . 27 , 15 . — !