إيجاد الطريقة الصحيحة لفصل محتوى الموقع باستخدام Webpack

يمكن أن يكون العثور على أفضل طريقة لتنظيم مواد مشروع الويب مهمة شاقة. هناك العديد من السيناريوهات المختلفة للمستخدمين للعمل مع المشاريع ، والعديد من التقنيات والعوامل الأخرى التي يجب أخذها في الاعتبار.

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

الصورة

معلومات عامة


وفقًا لـ Webpack Glossary ، هناك استراتيجيتان لمشاركة الملفات. هذا هو تقسيم الحزمة وتقسيم الكود. قد يبدو أن هذه المصطلحات تستخدم بالتبادل ، لكنها ليست كذلك.

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

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

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

لنتحدث عن هذا بمزيد من التفصيل.

فصل الحزم


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

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

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

عندما يتعلق الأمر بالزوار المنتظمين ، قد يكون من الصعب قياس تأثير تقنيات تحسين المواد المطبقة عليهم. ولكن يجب علينا ببساطة معرفة عواقب مثل هذه التحسينات.

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

في ما يلي نص برمجي يناسب الوصف العام الوارد في الفقرة السابقة:

  • تزور أليس موقعنا مرة واحدة في الأسبوع لمدة 10 أسابيع.
  • نقوم بتحديث الموقع مرة واحدة في الأسبوع.
  • كل أسبوع نقوم بتحديث صفحة قائمة المنتجات.
  • بالإضافة إلى ذلك ، لدينا صفحة تحتوي على تفاصيل المنتج ، لكننا لا نعمل على ذلك حتى الآن.
  • في الأسبوع الخامس ، نضيف حزمة npm جديدة إلى مواد المشروع.
  • في الأسبوع الثامن ، نقوم بتحديث إحدى حزم npm المستخدمة بالفعل في المشروع.

هناك أناس (مثلي) سيحاولون جعل مثل هذا السيناريو واقعيًا قدر الإمكان. لكنك لست بحاجة للقيام بذلك. السيناريو الحقيقي هنا لا يهم حقا. لماذا هذا - سنكتشف قريبا.

conditions الشروط الأولية


لنفترض أن الحجم الإجمالي لحزمة جافا سكريبت الخاصة بنا يبلغ 400 كيلوبايت كبير ، ونحن في الظروف الحالية ، ننقل كل هذا إلى المستخدم كملف main.js واحد. لدينا تكوين Webpack ، والذي يشبه ، بشكل عام ، ما يلي (أزلت الأشياء التي لا صلة لها بمحادثتنا):

 const path = require('path'); module.exports = { entry: path.resolve(__dirname, 'src/index.js'), output: {   path: path.resolve(__dirname, 'dist'),   filename: '[name].[contenthash].js', }, }; 

يقوم Webpack main.js ملف main.js الناتج عند وجود إدخال واحد في التكوين.

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

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

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


مقدار البيانات التي قام المستخدم بتحميلها

ونتيجة لذلك ، اتضح أن المستخدم ، في 10 أسابيع ، قام بتنزيل 4.12 ميجابايت من التعليمات البرمجية. يمكن تحسين هذا المؤشر.

epar فصل حزم الطرف الثالث عن الكود الرئيسي


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

 const path = require('path'); module.exports = { entry: path.resolve(__dirname, 'src/index.js'), output: {   path: path.resolve(__dirname, 'dist'),   filename: '[name].[contenthash].js', }, optimization: {   splitChunks: {     chunks: 'all',   }, }, }; 

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

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

على أي حال ، فإن إضافة optimization.splitChunks.chunks = 'all' إلى تكوين التكوين يخبر Webpack أننا بحاجة إليه لأخذ كل شيء من node_modules ووضعه في vendors~main.js

بعد أن قمنا بهذا الفصل الأساسي للحزمة ، ستقوم أليس ، التي تزور موقعنا بانتظام أسبوعيًا ، بتنزيل ملف main.js البالغ 200 كيلوبايت في كل مرة main.js . لكنها ستقوم بتنزيل ملف vendor.js ثلاث مرات فقط. سيحدث ذلك خلال الزيارات في الأسابيع الأولى والخامسة والثامنة. هذا هو الجدول المقابل ، حيث تتوافق أحجام vendor.js و vendor.js في الأسابيع الأربعة الأولى وتساوي 200 كيلوبايت ، حسب vendor.js القدر.


مقدار البيانات التي قام المستخدم بتحميلها

ونتيجة لذلك ، تبين أن كمية البيانات التي تم تنزيلها من قبل المستخدم على مدى 10 أسابيع كانت 2.64 ميغابايت. أي أنه مقارنة بما كان قبل فصل الحزمة ، انخفض الحجم بنسبة 36٪. لم يتم تحقيق هذه النتيجة السيئة بإضافة بضعة أسطر إلى ملف التكوين. بالمناسبة ، قبل قراءة المزيد - افعل نفس الشيء في مشروعك. وإذا كنت بحاجة إلى الترقية من Webpack 3 إلى 4 - فقم بذلك ولا تقلق ، لأن العملية بسيطة للغاية ولا تزال مجانية.

يبدو لي أن التحسن الذي تم النظر فيه هنا يبدو تجريديًا إلى حد ما ، حيث إنه يمتد على مدى 10 أسابيع. ومع ذلك ، إذا أخذنا في الاعتبار كمية البيانات المرسلة إلى مستخدم مخلص ، فإن هذا يعد تخفيضًا صريحًا في هذا الحجم بنسبة 36٪. هذه نتيجة جيدة جدًا ، ولكن يمكن تحسينها.

light تسليط الضوء على الحزم في ملفات منفصلة


يعاني ملف vendor.js من نفس المشكلة مثل main.js وهو يتألف من حقيقة أن تغيير أي حزمة مضمنة في هذا الملف يؤدي إلى الحاجة إلى قيام مستخدم عادي بتنزيل الملف بأكمله مرة أخرى.

لماذا لا نقوم بإنشاء ملفات منفصلة لكل حزمة npm؟ ليس من الصعب القيام بذلك ، لذا دعنا lodash react lodash ، lodash ، lodash ، lodash ، وما إلى ذلك في ملفات منفصلة. ستساعدنا تهيئة Webpack التالية في ذلك:

 const path = require('path'); const webpack = require('webpack'); module.exports = { entry: path.resolve(__dirname, 'src/index.js'), plugins: [   new webpack.HashedModuleIdsPlugin(), //        ], output: {   path: path.resolve(__dirname, 'dist'),   filename: '[name].[contenthash].js', }, optimization: {   runtimeChunk: 'single',   splitChunks: {     chunks: 'all',     maxInitialRequests: Infinity,     minSize: 0,     cacheGroups: {       vendor: {         test: /[\\/]node_modules[\\/]/,         name(module) {           //  ,   node_modules/packageName/not/this/part.js           //  node_modules/packageName           const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];           //  npm- ,   ,           //  URL,        @           return `npm.${packageName.replace('@', '')}`;         },       },     },   }, }, }; 

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

  • يحتوي Webpack على تركيبات قياسية معقولة جدًا ، وهي في الواقع ليست معقولة جدًا. على سبيل المثال ، يتم تعيين الحد الأقصى لعدد ملفات الإخراج إلى 3 ، والحد الأدنى لحجم الملف هو 30 كيلوبايت (أي ، سيتم دمج الملفات الأصغر). لقد أعدت تعريفه.
  • cacheGroups هو المكان الذي نضع فيه القواعد لكيفية تجميع Webpack للبيانات في ملفات الإخراج. لدي مجموعة واحدة هنا ، هي vendor ، والتي سيتم استخدامها لأي وحدة محملة من node_modules . عادة ما يتم إعطاء اسم ملف الإخراج كسلسلة. ولكن أعطيت name كدالة سيتم استدعاؤها لكل ملف تمت معالجته. ثم آخذ اسم الحزمة من مسار الوحدة النمطية. ونتيجة لذلك ، نحصل على ملف واحد لكل حزمة. على سبيل المثال ، npm.react-dom.899sadfhj4.js .
  • يجب أن تكون أسماء الحزم ، حتى يمكن نشرها في npm ، مناسبة للاستخدام في عناوين URL ، لذلك لا نحتاج إلى إجراء عملية encodeURI على أسماء packageName . ومع ذلك ، واجهت مشكلة أن خادم .NET يرفض العمل مع الملفات التي تحتوي على الرمز @ في أسمائها (يتم استخدام هذه الأسماء للحزم ذات نطاق اسم معين ، ما يسمى بالحزم المقيدة) ، لذلك ، في المقابل جزء التعليمات البرمجية ، أتخلص من هذه الشخصيات.

يعد التكوين السابق لـ Webpack جيدًا حيث يمكنك تكوينه مرة واحدة ، ثم نسيانه. لا يتطلب الرجوع إلى حزم محددة بالاسم ، وبالتالي ، بعد إنشائها ، تظل ، حتى عند تغيير تكوين الحزم ، ذات صلة.

لا تزال أليس ، main.js المنتظم ، main.js 200 كيلوبايت كل أسبوع ، وفي المرة الأولى التي تزور فيها الموقع ، يتعين عليها تنزيل 200 كيلوبايت من حزم npm ، ولكن ليس عليها تنزيل الحزم نفسها مرتين.

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


مقدار البيانات التي قام المستخدم بتحميلها

الآن حجم البيانات التي تم تنزيلها في 10 أسابيع هو 2.24 ميجا بايت. وهذا يعني أننا قمنا بتحسين المعدل الأساسي بنسبة 44٪. والنتيجة جيدة جدًا بالفعل ، ولكن السؤال الذي يطرح نفسه هو ما إذا كان من الممكن القيام بذلك من أجل تحقيق نتيجة تتجاوز 50 ٪. إذا حدث هذا ، فسيكون رائعًا.

code تقسيم كود التطبيق إلى أجزاء


نعود إلى ملف main.js ، الذي يجب على أليس المؤسف تنزيله باستمرار.

كما قلت أعلاه ، هناك قسمان منفصلان على موقعنا. الأول عبارة عن قائمة بالمنتجات ، والثاني صفحة تحتوي على معلومات تفصيلية حول المنتج. حجم الكود ، الفريد لكل منهم ، هو 25 كيلوبايت (و 150 كيلوبايت من الكود يستخدم هناك وهناك).

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

بالإضافة إلى ذلك ، كما اتضح ، لدينا ملف SVG ضخم مضمن يستخدم لعرض الرموز ، والذي يزن ما يصل إلى 25 كيلوبايت ونادراً ما يتغير.

شيء ما يجب القيام به مع هذا.

لقد أنشأنا يدويًا عدة نقاط إدخال ، لإخبار Webpack أنه بحاجة إلى إنشاء ملف منفصل لكل من هذه الكيانات.

 module.exports = { entry: {   main: path.resolve(__dirname, 'src/index.js'),   ProductList: path.resolve(__dirname, 'src/ProductList/ProductList.js'),   ProductPage: path.resolve(__dirname, 'src/ProductPage/ProductPage.js'),   Icon: path.resolve(__dirname, 'src/Icon/Icon.js'), }, output: {   path: path.resolve(__dirname, 'dist'),   filename: '[name].[contenthash:8].js', }, plugins: [   new webpack.HashedModuleIdsPlugin(), //        ], optimization: {   runtimeChunk: 'single',   splitChunks: {     chunks: 'all',     maxInitialRequests: Infinity,     minSize: 0,     cacheGroups: {       vendor: {         test: /[\\/]node_modules[\\/]/,         name(module) {           //  ,   node_modules/packageName/not/this/part.js           //  node_modules/packageName           const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];           //  npm- ,   ,           //  URL,        @           return `npm.${packageName.replace('@', '')}`;         },       },     },   }, }, }; 

بالإضافة إلى ذلك ، ستنشئ حزمة Webpack التي تعمل بجد ملفات لما هو شائع ، على سبيل المثال ، ProductList و ProductPage ، أي أنه لن يكون هناك كود مكرر.

ما فعلناه للتو سيسمح لأليس بتوفير 50 ​​كيلوبايت من حركة المرور كل أسبوع تقريبًا. يرجى ملاحظة أننا قمنا بتحرير ملف وصف الرمز في الأسبوع السادس. هنا مائدتنا التقليدية.


مقدار البيانات التي قام المستخدم بتحميلها

الآن في غضون عشرة أسابيع فقط ، تم تنزيل 1.815 ميغابايت فقط من البيانات. وهذا يعني أن وفورات المرور كانت رائعة بنسبة 56٪. وفقًا لسيناريونا النظري ، سيعمل المستخدم العادي دائمًا مع هذا المستوى من المدخرات.

كل هذا يتم بسبب التغييرات التي تم إجراؤها على تكوين Webpack. لم نغير رمز التطبيق لتحقيق هذه النتائج.

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

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

▍ السؤال رقم 1. هل الحاجة لأداء العديد من الطلبات لا يضر بسرعة تحميل الموقع؟


يمكنك إعطاء إجابة قصيرة بسيطة على هذا السؤال: "لا ، هذا لا يؤذي". نتج عن موقف مماثل مشكلة في الأيام الخوالي ، عندما كان بروتوكول HTTP / 1.1 قيد الاستخدام ، وعند استخدام HTTP / 2 ، لم يعد هذا ملائمًا.

على الرغم من ذلك ، تجدر الإشارة إلى أنه في هذه المقالة ، المنشورة في عام 2016 ، وفي مقال أكاديمية خان 2015 ، يتم استخلاص الاستنتاجات أنه حتى عند استخدام HTTP / 2 ، فإن استخدام الكثير من الملفات يبطئ التنزيل. ولكن في كلتا هاتين المادتين ، تعني عبارة "أكثر من اللازم" "عدة مئات". لذلك ، تجدر الإشارة إلى أنه إذا كان عليك العمل مع مئات الملفات ، فقد تؤثر القيود على معالجة البيانات المتوازية على سرعة التنزيل.

إذا كنت مهتمًا ، يتوفر دعم HTTP / 2 في IE 11 على Windows 10. بالإضافة إلى ذلك ، أجريت دراسة شاملة بين أولئك الذين يستخدمون أنظمة قديمة. ذكروا بالإجماع أن سرعة تحميل موقع الويب الخاص بهم لم تكن مقلقة بشكل خاص.

▍ سؤال رقم 2. تحتوي حزم Webpack على رمز مساعد. هل يخلق حمولة إضافية على النظام؟


نعم إنه كذلك.

▍ سؤال رقم 3. عند العمل مع العديد من الملفات الصغيرة ، يتدهور مستوى ضغطها ، أليس كذلك؟


نعم هذا صحيح ايضا في الواقع ، أود أن أقول هذا:

  • المزيد من الملفات يعني المزيد من التعليمات البرمجية المساعد Webpack.
  • المزيد من الملفات يعني ضغط أقل.

دعونا نفهم ذلك من أجل فهم مدى سوء ذلك.

لقد أجريت للتو اختبارًا تم فيه تقسيم الرمز من ملف 190 كيلوبايت إلى 19 جزءًا. أضاف هذا حوالي 2٪ إلى كمية البيانات المرسلة إلى المتصفح.

ونتيجة لذلك ، اتضح أنه في أول زيارة للموقع ، سيقوم المستخدم بتحميل المزيد من البيانات بنسبة 2٪ ، وفي الزيارات اللاحقة - أقل بنسبة 60٪ ، وسيستمر هذا لفترة طويلة جدًا جدًا.
فهل يستحق الأمر أن تقلق؟ لا ، لا يستحق ذلك.

عندما قارنت نظامًا باستخدام ملف واحد ونظام به 19 ملفًا ، اختبرته باستخدام بروتوكولات مختلفة ، بما في ذلك HTTP / 1.1. يدعم الجدول أدناه بقوة فكرة أن وجود المزيد من الملفات يعني أفضل.


بيانات عن العمل باستخدام نسختين من موقع مستضاف على استضافة ثابتة من Firebase ، يبلغ حجم رمزها 190 كيلوبايت ، ولكن في الحالة الأولى ، يتم تعبئتها في ملف واحد ، وفي الثانية يتم تقسيمها إلى 19

عند العمل في شبكات 3G و 4G ، استغرق تنزيل موقع يحتوي على 19 ملفًا وقتًا أقل بنسبة 30٪ من تنزيل موقع بملف واحد.

هناك الكثير من الضجيج في البيانات المقدمة في الجدول. على سبيل المثال ، استغرقت جلسة واحدة لتنزيل موقع بواسطة 4G (Run 2 في الجدول) 646 مللي ثانية ، وجلسة أخرى (Run 4) - 1116 مللي ثانية ، وهي أطول بنسبة 73٪. لذلك ، هناك شعور بأن القول بأن HTTP / 2 "أسرع بنسبة 30٪" هو أمر غير شريف إلى حد ما.

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

كان آخر سطرين في هذا الجدول مفاجأة حقيقية. فيما يلي نتائج أحدث إصدار من Windows مع IE11 و HTTP / 1.1. إذا حاولت التنبؤ بنتائج الاختبار مقدمًا ، سأقول بالتأكيد أن مثل هذا التكوين سيؤدي إلى تحميل المواد بشكل أبطأ بكثير من الآخرين. صحيح ، تم استخدام اتصال شبكة سريع جدًا هنا ، وأنا ، لمثل هذه الاختبارات ، ربما يجب أن أستخدم شيئًا أبطأ.

وسأخبركم الآن قصة واحدة. لاستكشاف موقعي على نظام قديم جدًا ، قمت بتنزيل جهاز Windows 7 الظاهري من موقع Microsoft على الويب . تم تثبيت IE8 هناك ، وقررت الترقية إلى IE9. للقيام بذلك ، انتقلت إلى صفحة Microsoft المصممة لتنزيل IE 9. لكنني لم أستطع القيام بذلك.


هذا الحظ السيئ ...

بالمناسبة ، إذا تحدثنا عن HTTP / 2 ، أود أن أشير إلى أن هذا البروتوكول مدمج في Node.js. إذا كنت ترغب في التجربة ، يمكنك استخدام خادم HTTP / 2 الصغير الذي كتبته مع دعم ذاكرة التخزين المؤقت للاستجابة و gzip و brotli.

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

الآن لنتحدث عن فصل الكود.

فصل الكود


الفكرة الرئيسية لتقنية تقسيم الكود هي: "لا تقم بتنزيل الكود غير الضروري". قيل لي أن استخدام هذا النهج أمر منطقي فقط لبعض المواقع.

أفضّل ، عندما يتعلق الأمر بفصل الشفرة ، استخدام قاعدة 20/20 التي صاغتها للتو. إذا كان هناك جزء من الموقع تتم زيارته من قبل 20٪ فقط من المستخدمين ، ويتم توفير وظائفه بواسطة أكثر من 20٪ من شفرة JavaScript للموقع ، فيجب تنزيل هذا الرمز فقط عند الطلب.

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

▍ منفصل أم لا؟


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

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

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

لذلك ، اكتشفت أن رمزًا فريدًا تمامًا لقسم الموقع المستخدم للدفع مقابل المشتريات يستغرق 7 كيلوبايت. حجم باقي كود الموقع 300 كيلوبايت. في مثل هذه الحالة ، لن أشارك في فصل الرمز لعدة أسباب:

  • إذا قمت بتنزيل 7 كيلوبايت مسبقًا ، فلن يتباطأ الموقع. تذكر أن الملفات يتم تنزيلها بالتوازي وحاول قياس الفرق المطلوب لتنزيل كود 300 كيلو بايت و 307 كيلو بايت.
  • إذا قمت بتنزيل هذا الرمز لاحقًا ، فسيتعين على المستخدم الانتظار بعد النقر على زر "الدفع". وهذه هي اللحظة التي تحتاج فيها إلى كل شيء للذهاب بسلاسة قدر الإمكان.
  • يتطلب فصل الرمز تغييرات في التطبيق. في الكود ، في الأماكن التي تم فيها عمل كل شيء بشكل متزامن من قبل ، يظهر المنطق غير المتزامن. , , , , , .

, , , .

.


, , , .

. , . :

 require('whatwg-fetch'); require('intl'); require('url-polyfill'); require('core-js/web/dom-collections'); require('core-js/es6/map'); require('core-js/es6/string'); require('core-js/es6/array'); require('core-js/es6/object'); 

index.js , :

 import './polyfills'; import React from 'react'; import ReactDOM from 'react-dom'; import App from './App/App'; import './index.css'; const render = () => { ReactDOM.render(<App />, document.getElementById('root')); } render(); // ,      

Webpack , , npm-. 25 , 90% , .

Webpack 4 import() ( import ), :

 import React from 'react'; import ReactDOM from 'react-dom'; import App from './App/App'; import './index.css'; const render = () => { ReactDOM.render(<App />, document.getElementById('root')); } if ( 'fetch' in window && 'Intl' in window && 'URL' in window && 'Map' in window && 'forEach' in NodeList.prototype && 'startsWith' in String.prototype && 'endsWith' in String.prototype && 'includes' in String.prototype && 'includes' in Array.prototype && 'assign' in Object && 'entries' in Object && 'keys' in Object ) { render(); } else { import('./polyfills').then(render); } 

, , , — . — render() . , Webpack npm-, , render() .

, import() Babel dynamic-import . , Webpack, import() , .

, . .

▍ React,


. , , , .

, npm- . , , 100 .

, , URL /admin , <AdminPage> . Webpack , import AdminPage from './AdminPage.js' .

. , , import('./AdminPage.js') , Webpack , .

, .

, , AdminPage , , URL /admin . , :

 import React from 'react'; class AdminPageLoader extends React.PureComponent { constructor(props) {   super(props);   this.state = {     AdminPage: null,   } } componentDidMount() {   import('./AdminPage').then(module => {     this.setState({ AdminPage: module.default });   }); } render() {   const { AdminPage } = this.state;   return AdminPage     ? <AdminPage {...this.props} />     : <div>Loading...</div>; } } export default AdminPageLoader; 

. (, URL /admin ), ./AdminPage.js , .

render() , <AdminPage> , <div>Loading...</div> , <AdminPage> , .

, react-loadable , React .

الملخص


, , (, , CSS). :

  • — .
  • , — .

أعزائي القراء! ?

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


All Articles