ننشر اليوم الجزء الثاني من ترجمة المادة ، المكرس لاستخدام وحدات JS في الإنتاج.

→ بالمناسبة ، هنا هو
الجزء الأول من المقال.
استيراد ديناميكي
أحد عيوب استخدام تعبيرات الاستيراد الحقيقية لفصل وحدات الكود والتحميل هي أن مهمة العمل مع المتصفحات التي لا تدعم الوحدات النمطية تقع على عاتق المطور.
وإذا كنت ترغب في استخدام أوامر
import()
الديناميكية لتنظيم عملية تحميل الكود البطيء ، فسيتعين عليك ، من بين أشياء أخرى ، التعامل مع حقيقة أن بعض المتصفحات ، على الرغم من أنها بالتأكيد
تدعم الوحدات النمطية ، لا تزال
لا تدعم أوامر import () الديناميكية (الحافة 16-18 ، Firefox 60-66 ، Safari 11 ، Chrome 61–63).
لحسن الحظ ، ستساعدنا هذه المشكلة على حل حجم صغير (حوالي 400 بايت)
وملف متعدد سريع للغاية.
تعد إضافة polyfill إلى مشروع ويب أمرًا بسيطًا للغاية. تحتاج فقط إلى استيراده وتهيئته عند نقطة الإدخال الرئيسية للتطبيق (قبل استدعاء أي من أوامر
import()
في الكود):
import dynamicImportPolyfill from 'dynamic-import-polyfill';
وآخر شيء يجب القيام به حتى يعمل هذا المخطط ، هو إخبار Rollup بأنه يحتاج إلى إعادة تسمية أوامر
import()
الديناميكية التي تظهر في الكود باستخدام الاسم الذي
تختاره (عبر خيار
output.dynamicImportFunction ). يستخدم
__import__
الذي يقوم بتنفيذ ميزة الاستيراد الديناميكية اسم
__import__
افتراضيًا ، لكن يمكن
تخصيصه .
سبب احتياجك لإعادة تسمية تعبيرات
import()
هو أن
import
، في JavaScript ، هو كلمة أساسية. هذا يعني أنه من المستحيل ، عن طريق polyfill ، تنظيم عملية استبدال أمر
import()
القياسي بأمر يحمل نفس الاسم. إذا حاولت القيام بذلك ، فسيحدث خطأ في بناء الجملة.
لكن من الجيد جدًا أن يقوم Rollup بإعادة تسمية الأوامر أثناء إنشاء المشروع ، لأن هذا يعني أنه يمكنك استخدام الأوامر القياسية في التعليمات البرمجية المصدر. بالإضافة إلى ذلك ، في المستقبل ، عندما لن تكون هناك حاجة إلى polyfill ، لن تتم إعادة كتابة التعليمات البرمجية المصدر للمشروع ، مع تغيير
import
ما تم تسميته مسبقًا بطريقة مختلفة بطريقة ما.
جافا سكريبت التحميل
عندما تستخدم فصل الكود ، لن يضر بتنظيم التحميل المسبق لجميع الوحدات التي تعرف أنها سيتم تحميلها قريبًا جدًا (على سبيل المثال ، هذه كلها وحدات في شجرة التبعية للوحدة الرئيسية ، وهي نقطة الدخول إلى المشروع).
ولكن عندما نقوم بتحميل وحدات جافا سكريبت حقيقية (عبر
<script type="module">
ثم من خلال أوامر
import
المطابقة) ، يجب علينا استخدام سمة
modulepreload بدلاً من
التحميل المسبق المعتاد ،
والمخصص فقط للبرامج النصية الكلاسيكية.
<link rel="modulepreload" href="/modules/main.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-one.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-two.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-three.XXXX.mjs"> <!-- ... --> <script type="module" src="/modules/main.XXXX.mjs"></script>
في الواقع ، يعد
modulepreload
بالتأكيد أفضل من آلية
preload
التقليدية في تحميل الوحدات النمطية الحقيقية. الحقيقة هي أنه عند استخدامه ، لا يتم تنزيل الملف فقط. بالإضافة إلى ذلك ، يبدأ على الفور ، خارج الخيط الرئيسي ، في تحليل وتجميع البرنامج النصي. يتعذر على
preload
العادي القيام بذلك لأنه ، أثناء التحميل المسبق ، لا يعرف ما إذا كان سيتم استخدام الملف كوحدة نمطية أو كبرنامج نصي عادي.
هذا يعني أن تحميل الوحدات النمطية باستخدام سمة
modulepreload
غالبًا ما يكون أسرع ، وأنه عندما تتم تهيئة الوحدات النمطية ، يكون من غير المحتمل إنشاء حمل
modulepreload
على مؤشر الترابط الرئيسي ، مما يؤدي إلى حدوث مشكلات في الواجهة.
إنشاء قائمة الوحدات النمطية للتحميل المسبق
يحتوي جزء الإدخال في كائن
حزمة Rollup على قائمة كاملة من عمليات الاستيراد في أشجار التبعية الثابتة الخاصة بهم. نتيجة لذلك ، في ربط Rollup GenerateBundle ، من السهل الحصول على قائمة بالملفات التي تحتاج إلى تحميلها مسبقًا.
على الرغم من أنه يمكن العثور على المكونات الإضافية في npm لإنشاء قوائم تحميل وحدة نمطية ، فإن إنشاء قائمة مشابهة لكل نقطة إدخال في شجرة التبعية لا يتطلب سوى بضعة أسطر من التعليمات البرمجية. لذلك ، أفضل إنشاء مثل هذه القوائم يدويًا ، باستخدام شيء مثل هذا الرمز:
{ generateBundle(options, bundle) {
هنا ، على سبيل المثال ، كيف قمت بإنشاء
قائمة تحميل وحدة
نمطية لـ
philipwalton.com وللتطبيق التجريبي الخاص بي ، والذي سنتحدث عنه أدناه.
يرجى ملاحظة أنه على الرغم من أن سمة
modulepreload
أفضل بالتأكيد من
preload
الكلاسيكي للنصوص النمطية للوحدة النمطية ، إلا أنها توفر أسوأ دعم للمتصفح (يدعمها Chrome حاليًا فقط). إذا كان جزء كبير من
preload
لا يأتي من Chrome ، فقد يكون من المنطقي في هذه الحالة استخدام
preload
المنتظم بدلاً من
preload
.
فيما يتعلق باستخدام
preload
، أود أن أحذرك بشأن شيء ما. الحقيقة هي أنه عند تحميل البرامج النصية باستخدام
preload
، على عكس
modulepreload
الوحدة النمطية ، لا
modulepreload
هذه البرامج النصية في خريطة وحدة المتصفح. هذا يعني أن هناك احتمال أن طلبات التحميل المسبق يمكن تنفيذها أكثر من مرة (على سبيل المثال ، إذا كانت الوحدة النمطية تستورد الملف قبل انتهاء المتصفح من التحميل المسبق).
لماذا نشر وحدات حقيقية في الإنتاج؟
إذا كنت تستخدم بالفعل حزمة مثل
webpack ، وكذلك إذا كنت تستخدم بالفعل تقسيم الشفرة وتحميل الملفات المقابلة مسبقًا (على غرار ما قلته للتو) ، فقد تتساءل عما إذا كان يجب عليك التبديل إلى استراتيجية ركز على استخدام وحدات حقيقية. هناك عدة أسباب تجعلني أعتقد أنه يجب عليك التفكير في التبديل إلى الوحدات النمطية. بالإضافة إلى ذلك ، أعتقد أن تحويل مشروع إلى وحدات حقيقية أفضل من استخدام البرامج النصية الكلاسيكية مع التعليمات البرمجية الخاصة بها المصممة لتحميل الوحدات.
▍ تقليل المبلغ الإجمالي للرمز
إذا كان المشروع يستخدم وحدات حقيقية ، فلن يتعين على مستخدمي المتصفحات الحديثة تنزيل بعض التعليمات البرمجية الإضافية المصممة لتحميل الوحدات النمطية أو لإدارة التبعيات. على سبيل المثال ، عند استخدام الوحدات النمطية الحقيقية ، لن تحتاج إلى تحميل
آليات وقت التشغيل وبيان webpack .
code تحسين رمز التحميل المسبق
كما هو مذكور في القسم السابق ، فإن استخدام سمة
modulepreload
يسمح
modulepreload
بتحميل الشفرة
modulepreload
الرئيسية. كل شيء آخر ، مقارنة
preload
، لا يزال كما هو. هذا يعني أنه بفضل
modulepreload
تصبح الصفحات تفاعلية بشكل أسرع ، مما يقلل من احتمال حظر الدفق الرئيسي أثناء تفاعل المستخدم.
كنتيجة لذلك ، بغض النظر عن حجم رمز التطبيق الذي يتم تقسيمه إلى أجزاء ، سيكون إنتاج هذه الأجزاء باستخدام أوامر الاستيراد وسمات
modulepreload
أكثر
modulepreload
من تحميلها باستخدام علامة
script
المعتادة
modulepreload
التحميل
preload
المعتادة (خاصةً إذا تم إنشاء العلامات المقابلة بشكل حيوي وإضافتها إلى DOM في وقت التشغيل).
بمعنى آخر ، سيتم تحميل حزمة مجموعة من بعض رموز المشروع ، تتكون من 20 جزء وحدة ، بشكل أسرع من حزمة من نفس المشروع ، والتي تتكون من 20 جزءًا نصيًا كلاسيكيًا تم تحضيرها بواسطة webpack (ليس بسبب استخدام webpack ، ولكن بسبب أن هذه ليست وحدات حقيقية).
focus تحسين التركيز في المستقبل من التعليمات البرمجية
يتم بناء العديد من الميزات الجديدة الرائعة للمتصفحات على أساس الوحدات النمطية ، ولا تستند إلى البرامج النصية الكلاسيكية. هذا يعني أنه إذا كنت تخطط لاستخدام هذه الميزات ، فينبغي تقديم الشفرة في شكل وحدات حقيقية. يجب ألا يكون هناك شيء تم نقله في ES5 ومُحمّل بوسائل علامة
script
الكلاسيكية (هذه هي المشكلة التي كتبت عنها عندما حاولت استخدام
واجهة برمجة تطبيقات التخزين KV Storage ).
فيما يلي بعض ميزات المتصفح الجديدة الأكثر إثارة للاهتمام والتي تركز حصريًا على الوحدات النمطية:
دعم المتصفح القديم
على المستوى العالمي ، يدعم
أكثر من 83٪ من المتصفحات وحدات جافا سكريبت JavaScript (بما في ذلك الاستيراد الديناميكي) ، ونتيجة لذلك ، سيتمكن معظم المستخدمين من العمل مع مشروع تحول إلى وحدات نمطية دون أي جهد خاص من جانب مطوري هذا المشروع.
في حالة المتصفحات التي تدعم الوحدات النمطية ولكنها لا تدعم الاستيراد الديناميكي ، يوصى باستخدام
polyfill الديناميكي للاستيراد polyfill الموضح أعلاه. نظرًا لأنه صغير جدًا ، وإذا كان ذلك ممكنًا ، يستخدم طريقة
import()
القياسية المستندة إلى المستعرض ، فإن استخدام هذا polyfill ليس له أي تأثير تقريبًا على حجم المشروع أو أدائه.
إذا كنا نتحدث عن المتصفحات التي لا تدعم وحدات على الإطلاق ، إذن ، لتنظيم العمل معهم ، يمكنك استخدام
نمط الوحدة / الترميز .
مثال التشغيل
نظرًا لأنه من الأسهل دائمًا التحدث عن التوافق عبر المستعرض بدلاً من تحقيقه ، فقد أنشأت
تطبيقًا تجريبيًا يستخدم التقنيات التي تمت مناقشتها أعلاه.
يعمل هذا التطبيق في متصفحات مثل Edge 18 و Firefox ESR ، والتي لا تدعم أوامر
import()
الديناميكية. بالإضافة إلى ذلك ، يعمل في متصفحات مثل Internet Explorer 11 ، والتي لا تدعم الوحدات النمطية.
لإظهار أن الإستراتيجية التي تمت مناقشتها هنا مناسبة ليس فقط للمشاريع البسيطة ، فقد استخدمت العديد من الميزات في هذا التطبيق والتي نحتاجها اليوم في المشروعات الكبيرة:
- تحويل الكود باستخدام بابل (بما في ذلك JSX).
- تبعيات CommonJS (مثل التفاعل ورد الفعل dom).
- تبعيات CSS.
- تجزئة الموارد
- فصل الكود
- استيراد ديناميكي (مع تراجع كما polyfill).
- تنفيذ نمط الوحدة / نموذج الترميز.
يمكن العثور على رمز المشروع على
GitHub (أي ، يمكنك تفرع المستودع وإنشاء المشروع بنفسك) ، ويتم استضافة الإصدار التجريبي على
Glitch ، والذي يسمح لك بتجربته.
أهم شيء في المشروع التجريبي هو
تكوين مجموعة التحديثات ، حيث إنه يحدد كيفية إنشاء الوحدات النمطية الناتجة.
النتائج
آمل أن تكون هذه المادة قد أقنعتك ليس فقط بإمكانية نشر وحدات JavaScript القياسية في الإنتاج ، ولكن أيضًا يمكنها أن تحسن وقت تحميل الموقع وأدائه.
فيما يلي نظرة عامة مختصرة على الخطوات التي تحتاج إلى اتخاذها من أجل تنفيذ الوحدات النمطية في المشروع:
- استخدم أداة تجميع ، من بين تنسيقات الإخراج التي تدعمها وحدات ES2015.
- اقترب من الفصل بين الكود (إن أمكن ، وصولاً إلى تخصيص التبعيات من
node_modules
إلى أجزاء منفصلة). - التحميل المسبق لجميع الوحدات الموجودة في شجرة التبعية الثابتة (باستخدام
modulepreload
). - استخدم polyfill للمتصفحات التي لا تدعم عبارات
import()
الحيوية. - استخدم نمط الوحدة النمطية / nomodule لتنظيم العمل مع المتصفحات التي لا تدعم الوحدات النمطية.
إذا كنت تستخدم Rollup بالفعل لإنشاء المشروع ، أود منك أن تجرب ما كنت أتحدث عنه هنا وأن أذهب لنشر وحدات حقيقية في الإنتاج (باستخدام فصل الكود وتقنيات الاستيراد الديناميكية). إذا قمت بذلك ،
اسمحوا لي أن أعرف كيف حالك. أنا مهتم بمعرفة المشكلات والحالات الناجحة لإدخال الوحدات النمطية.
من الواضح جدًا أن الوحدات هي مستقبل JavaScript. أود أن أرى ، ومن المفضل قريبًا ، كيف تعتمد الأدوات التي نستخدمها والمكتبات المساعدة هذه التكنولوجيا. آمل أن تساعد هذه المواد على الأقل هذه العملية قليلاً.
أعزائي القراء! هل تستخدم وحدات JS في الإنتاج؟
