
ملاحظة سريعة حول كيفية ترحيل Chrome DevTools من أداة تحميل الوحدة الداخلية إلى وحدات JavaScript النمطية القياسية. سنخبرك عن مقدار التأخير في الترحيل وسببه ، والتكاليف الخفية للترحيل واستنتاجات فريق DevTools بعد اكتمال الترحيل. لكن لنبدأ بتاريخ أدوات مطوري الويب.
المقدمة
كما تعلم على الأرجح ، فإن Chrome DevTools هو تطبيق ويب HTML و CSS وجافا سكريبت. على مر السنين ، أصبحت DevTools غنية بالميزات وذكية ومعرفة بمنصة الويب الحديثة. على الرغم من أن DevTools قد توسع ، فإن بنيته تذكرنا إلى حد كبير بالأصل عندما كانت الأداة جزءًا من WebKit .
سنروي قصة DevTools ، وسنصف فوائد وقيود الحلول ، وما فعلناه للتخفيف من هذه القيود. لذلك دعونا نتعمق في الأنظمة المعيارية ، وكيفية تحميل التعليمات البرمجية ، وكيف انتهى بنا الأمر باستخدام وحدات JavaScript النمطية.
في البداية لم يكن هناك شيء
تحتوي الواجهة الأمامية الآن على العديد من الأنظمة المعيارية وأدواتها ، بالإضافة إلى تنسيق وحدة JavaScript قياسي . لم يكن أي من هذا عندما بدأ DevTools. الأداة مبنية على رمز WebKit المكتوب منذ أكثر من 12 عامًا.
يعود أول ذكر للنظام المعياري في DevTools إلى عام 2012: كان تقديم قائمة من الوحدات مع قائمة مصادر مقابلة . جزء من بنية Python الأساسية المستخدمة في ذلك الوقت لتجميع وإنشاء DevTools. في عام 2013 ، تم سحب الوحدات في ملف بواسطة
frontend_modules.json هذا الالتزام ، ثم في عام 2014 ، في وحدات منفصلة module.json( هنا ). مثال module.json:
{
"dependencies": [
"common"
],
"scripts": [
"StylePane.js",
"ElementsPanel.js"
]
}
منذ عام 2014 ،
module.jsonتستخدم في أدوات المطور للإشارة إلى الوحدات والملفات المصدر. في غضون ذلك ، نما النظام البيئي للويب بسرعة وتم إنشاء العديد من تنسيقات الوحدات: UMD و CommonJS وفي النهاية وحدات JavaScript النمطية الموحدة. ومع ذلك ، فإن DevTools عالق module.json. كان للنظام المعياري الفريد غير القياسي العديد من العيوب:
module.jsonيتطلب أدوات البناء الخاصة به.- لم يكن هناك تكامل IDE. بالطبع ، طلبت أدوات خاصة لإنشاء الملفات التي فهمتها: (
jsconfig.jsonلـ VS Code ). - تم وضع الوظائف والفئات والكائنات في النطاق العالمي للسماح بالمشاركة بين الوحدات.
- كان الترتيب الذي تم به سرد الملفات مهمًا. لم يكن هناك ما يضمن أنه تم تحميل الرمز الذي تعتمد عليه بخلاف التحقق البشري.
بشكل عام ، عند تقييم الحالة الحالية للنظام المعياري DevTools وتنسيقات الوحدات النمطية الأخرى الأكثر استخدامًا ، توصلنا إلى استنتاج مفاده أنه
module.jsonتسبب في مشاكل أكثر مما تم حلها.
مزايا المعيار
لقد اخترنا وحدات JavaScript. عندما تم اتخاذ هذا القرار ، كانت الوحدات النمطية في اللغة لا تزال تحمل علامة في Node.js ولم يدعمها عدد كبير من حزم NPM. بغض النظر ، خلصنا إلى أن وحدات JavaScript كانت الخيار الأفضل.
الميزة الرئيسية للوحدات هي أنها تنسيق موحد للغة . عندما قمنا بإدراج السلبيات
module.json، أدركنا أن جميعها تقريبًا كانت مرتبطة باستخدام تنسيق وحدة فريد غير موحد. يعني اختيار تنسيق وحدة غير قياسي أنه يتعين علينا استثمار الوقت في بناء عمليات التكامل باستخدام أدوات البناء وأدوات زملائنا. غالبًا ما كانت عمليات الدمج هشة وتفتقر إلى دعم الميزات ، وتتطلب وقتًا إضافيًا للصيانة وأحيانًا أخطاء صعبة. انتهى الخلل بضرب المستخدمين.
نظرًا لأن وحدات JavaScript قياسية ، فإن هذا يعني أن IDEs مثل VS Code ، وأدوات التحقق من النوع مثل مترجم Closure / TypeScript ، وأدوات البناء مثل Rollup و minifiers ستكون قادرة على فهم كود المصدر المكتوب. علاوة على ذلك ، عندما ينضم شخص جديد إلى فريق DevTools ، فلن يضطر إلى إضاعة الوقت في تعلم الملكية
module.json.
بالطبع ، عندما بدأت DevTools لأول مرة ، لم يكن هناك أي من المزايا المذكورة أعلاه. استغرق الأمر سنوات من العمل في مجموعات المعايير لتنفيذ وقت التشغيل. استغرق الأمر وقتًا للحصول على تعليقات من المطورين - مستخدمي الوحدات. ولكن عندما ظهرت الوحدات في اللغة ، كان لدينا خيار: إما الاستمرار في دعم التنسيق الخاص بنا ، أو الاستثمار في الانتقال إلى التنسيق الجديد.
كم يكلف لمعان الحداثة؟
على الرغم من أن وحدات JavaScript لديها العديد من الفوائد التي أردنا استخدامها ، إلا أننا بقينا في العالم
module.json. كان الاستفادة من وحدات اللغة يعني أنه كان علينا استثمار جهد كبير في الديون الفنية. في غضون ذلك ، قد يؤدي الترحيل إلى تعطيل الوظائف وإدخال أخطاء الانحدار.
لم يكن الأمر يتعلق بما إذا كنا نستخدم وحدات جافا سكريبت. كان السؤال هو ما مدى تكلفة القدرة على استخدام وحدات جافا سكريبت . كان علينا أن نوازن بين خطر إزعاج المستخدمين مع الانحدار ، والوقت الذي يستغرقه المهندسون للترحيل ، وفترة التدهور في حالة النظام الذي سنعمل فيه.
تبين أن النقطة الأخيرة مهمة للغاية. على الرغم من أنه يمكننا نظريًا الوصول إلى وحدات JavaScript النمطية ، إلا أننا سننتهي أثناء الترحيل برمز يأخذ في الاعتبار نوعي الوحدات النمطية . لا يمثل هذا تحديًا تقنيًا فحسب ، بل يعني أيضًا أن جميع المهندسين العاملين في DevTools بحاجة إلى معرفة كيفية العمل في مثل هذه البيئة. سيتعين عليهم أن يسألوا أنفسهم باستمرار ، "ما الذي يحدث في هذا الكود ، هل هو
module.jsonJS ، وكيف يمكنني إجراء التغيير؟"
كانت التكلفة الكامنة للهجرة من حيث تدريب الزملاء أعلى مما توقعنا.بعد تحليل التكاليف ، توصلنا إلى استنتاج مفاده أنه لا يزال من المفيد التبديل إلى الوحدات في اللغة. لذلك كانت أهدافنا الرئيسية:
- تأكد من أن الوحدات القياسية مفيدة قدر الإمكان.
- تأكد من أن التكامل مع الوحدات الموجودة في القاعدة
module.jsonآمن ولا يؤدي إلى تأثير سلبي على المستخدم (أخطاء الانحدار وإحباط المستخدم). - توفير أدلة ترحيل DevTools. في المقام الأول من خلال الضوابط والموازين المضمنة في العملية لمنع الأخطاء العرضية.
جدول البيانات والتحويلات والديون الفنية
كان الهدف واضحا. لكن كان من
module.jsonالصعب التغلب على القيود . استغرق الأمر العديد من التكرارات والنماذج الأولية والتغييرات المعمارية قبل أن نتوصل إلى حل قابل للاستخدام. انتهى بنا الأمر بكتابة مستند مشروع باستراتيجية ترحيل. أعطت هذه الوثيقة تقديرًا أوليًا للوقت: 2-4 أسابيع.
استغرق الجزء الأكثر كثافة من الترحيل 4 أشهر ، ومرت 7 أشهر من البداية إلى النهاية!ومع ذلك ، فإن الخطة الأصلية صمدت أمام اختبار الزمن: أردنا تعليم وقت تشغيل DevTools لتحميل جميع الملفات بالطريقة القديمة لاستخدام تلك المدرجة في المصفوفة
scripts module.json، بينما modulesيجب تحميل جميع الملفات المدرجة في المصفوفة عن طريق استيراد لغة ديناميكي . أي ملف من شأنها أن تكون في مجموعة modulesيمكن أن تعمل مع importو exportمن ES6.
بالإضافة إلى ذلك ، أردنا الترحيل على مرحلتين. في النهاية ، قمنا بتقسيم المرحلة الأخيرة إلى مرحلتين فرعيتين: التصدير والاستيراد. تم تتبع الوحدات والمراحل في جدول بيانات كبير:

مقتطف من جدول الترحيل هنا.
مرحلة التصدير
كانت الخطوة الأولى هي إضافة بيانات تصدير لجميع الكيانات التي يجب مشاركتها بين الوحدات / الملفات. تم التحويل تلقائيًا عن طريق تشغيل برنامج نصي لكل مجلد . لنفترض أن
module.jsonهناك مثل هذا الكيان:
Module.File1.exported = function() {
console.log('exported');
Module.File1.localFunctionInFile();
};
Module.File1.localFunctionInFile = function() {
console.log('Local');
};
هذا
Moduleهو اسم الوحدة. File1- اسم الملف. في شجرة الكود ، يبدو الأمر كما يلي front_end/module/file1.JS:.
الكود أعلاه يترجم إلى هذا:
export function exported() {
console.log('exported');
Module.File1.localFunctionInFile();
}
export function localFunctionInFile() {
console.log('Local');
}
/** Legacy export object */
Module.File1 = {
exported,
localFunctionInFile,
};
لقد خططنا في الأصل لإعادة كتابة الاستيراد في ملف واحد في هذه المرحلة. على سبيل المثال ، في المثال أعلاه ، سنعيد الكتابة
Module.File1.localFunctionInFileإلى localFunctionInFile. ومع ذلك ، أدركنا أنه سيكون من الأسهل التشغيل الآلي والأكثر أمانًا للفصل بين التحولين. وبالتالي ، فإن "نقل جميع الكيانات في ملف واحد" ستصبح المرحلة الفرعية الثانية للاستيراد.
نظرًا لأن إضافة كلمة أساسية
exportتحول الملف من "نص برمجي" إلى "وحدة نمطية" ، فقد كان لابد من تحديث الكثير من البنية الأساسية لـ DevTools وفقًا لذلك. تضمن إطار العمل وقت تشغيل استيراد ديناميكي بالإضافة إلى أدوات مثل ESLint للتشغيل في وضع الوحدة النمطية.
كان أحد الأمور المزعجة هو أن اختباراتنا أجريت في وضع "غير صارم". تشير وحدات JavaScript النمطية إلى أن الملفات تعمل في الوضع المقيد. أثر هذا على الاختبارات. كما اتضح ، اعتمد عدد غير تافه من الاختبارات على وضع غير صارم ، بما في ذلك الاختبار الذي كان المشغل موجودًا فيه
with.
في النهاية، وتحديث (التصدير مضيفا) المجلد الأول جدا استغرق نحو أسبوع و عدة محاولات لإعادة .
مرحلة الاستيراد
بعد أن تم تصدير جميع الكيانات باستخدام بيانات التصدير ، بينما بقيت في النطاق العالمي بسبب القديم ، كان علينا تحديث جميع مراجع الكيانات ، إذا كانت في ملفات متعددة ، لاستخدام عمليات استيراد ES. الهدف النهائي هو إزالة جميع الصادرات منتهية الصلاحية من خلال مسح النطاق العالمي. تم التحويل تلقائيًا عن طريق تشغيل برنامج نصي لكل مجلد .
على سبيل المثال ، الكيانات التالية
module.json:
Module.File1.exported();
AnotherModule.AnotherFile.alsoExported();
SameModule.AnotherFile.moduleScoped();
تم التحويل إلى:
import * as Module from '../module/Module.js';
import * as AnotherModule from '../another_module/AnotherModule.js';
import {moduleScoped} from './AnotherFile.js';
Module.File1.exported();
AnotherModule.AnotherFile.alsoExported();
moduleScoped();
ومع ذلك ، فإن هذا النهج له محاذير:
- لم يتم تسمية كل كيان من حيث المبدأ
Module.File.symbolName. تم تسمية بعض الكياناتModele.Fileأو حتىModule.CompletelyDifferentName. يعني عدم التطابق أنه كان علينا إنشاء تعيين داخلي من الكائن العالمي القديم إلى الكائن الجديد المستورد. -
moduleScoped. ,Events, ,Events. , , ,importEvents. - , . , . , , . , , ( DevTools). , , .
JavaScript
في فبراير 2020 ، بعد 6 أشهر من البدء في سبتمبر 2019 ، تم إجراء عمليات التنظيف الأخيرة في واجهة المستخدم / المجلد. هكذا انتهت الهجرة بشكل غير رسمي. عندما هدأ الغبار ، وضعنا علامة رسميًا على اكتمال الترحيل في 5 مارس 2020 .
تعمل DevTools الآن مع وحدات JavaScript النمطية فقط. ما زلنا نضع بعض الكيانات في النطاق العالمي (في الملفات القديمة
module.js) للاختبارات القديمة أو التكامل مع أجزاء أخرى من أدوات المهندس المعماري. ستتم إزالتها بمرور الوقت ، لكننا لا نعتبرها تعيق التطوير. لدينا أيضًا دليل أسلوب لوحدات JavaScript النمطية .
الإحصاء
التقديرات المتحفظة لعدد CL (قائمة التغيير - وهو مصطلح مستخدم في Gerrit ، على غرار طلب سحب GitHub) المتضمن في هذه الهجرة هو حوالي 250 CL ، معظمها قام به مهندسان . ليس لدينا إحصائيات نهائية عن حجم التغييرات التي تم إجراؤها ، ولكن تقديرًا متحفظًا للصفوف التي تم تغييرها (مجموع الفرق المطلق بين الإدخالات والحذف لكل CL) هو ما يقرب من 30000 صف ، وهو ما يمثل حوالي 20٪ من جميع التعليمات البرمجية للواجهة الأمامية لـ DevTools .
الملف الأول الذي سيتم تصديره مدعوم في Chrome 79 ، والذي تم إصداره في الإصدار الثابت في ديسمبر 2019. التغيير الأخير للتبديل للاستيراد يأتي في Chrome 83 ، والذي تم إصداره في الإصدار الثابت في مايو 2020.
نحن على علم بانحدار واحد بسبب الترحيل في Chrome المستقر. إنجاز قانون المتكررة في شريط الأوامر اندلعت نتيجة ل تصدير الافتراضي دخيلة . كان هناك العديد من حالات الانحدار الأخرى ، لكن حالات الاختبار الآلي لدينا ومستخدمي Chrome Canary أبلغوا عنها. أصلحنا الأخطاء قبل أن يتمكنوا من تحويلها إلى إصدارات مستقرة من Chrome.
يمكنك مشاهدة القصة كاملة بالتسجيل هنا . ليس كل شيء ، ولكن معظم CL مرتبطة بهذا الخطأ.
ماذا تعلمنا؟
- . , JavaScript ( ) , DevTools . , , , .
- — , . , , . , , , .
- (, ) . -. , Python Rollup.
- (~20% ), . , , . , .
- , . . , , , . , , — . , , .
, Level Up , - SkillFactory:
- Java- (18 )
- JavaScript (12 )
E
- Data Science (12 )
- - (8 )
- Machine Learning (12 )
- «Machine Learning Pro + Deep Learning» (20 )
- « Machine Learning Data Science» (20 )
- «Python -» (9 )
- DevOps (12 )
- (9 )
- UX- (9 )
- Web- (7 )
