ترجمة قوالب الغبار إلى JSX



مرحبا حبر! أنا Miloš من Badoo ، وهذا هو أول منشور لي Habr ، نُشر في الأصل في مدونة التقنية الخاصة بنا. آمل أن تكونوا مثل ذلك ، يرجى المشاركة والتعليق إذا كان لديك أي أسئلة

إذاً ... رد فعل ، أميريت ؟؟؟

لقد ظهر في منتصف العقد (الذي ابتليت به حروب إطار جافا سكريبت التي لا نهاية لها) ، واحتضنت DOM ، صدمت الجميع من خلال مزج HTML مع جافا سكريبت وتحويل مشهد تطوير الويب إلى درجة لا يمكن التعرف عليها.

كل هذه الإنجازات ، دون أن يكون إطارًا .

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


هنا في فريق Mobile Web ، لا نتبع أي أطر JS صارمة - أو على الأقل ، أي منها شائع - ونحن نستخدم مزيجًا من التقنيات القديمة والتقنيات الحديثة. على الرغم من أن ذلك يعمل بشكل جيد بالنسبة إلينا ، إلا أن التعامل مع DOM عادة ما يكون أمرًا صعبًا ، وأردنا تخفيف ذلك عن طريق تقليل عدد التحديثات "اليدوية" ، وزيادة إعادة استخدام الكود لدينا والقلق بشأن تسريبات الذاكرة.

بعد إجراء بعض التحقيقات ، اعتبر React الخيار الأفضل وقررنا الذهاب معه.

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

Jsx


React يمزج HTML مع جافا سكريبت بتنسيق اسمه JSX . على الرغم من أنها تبدو وكأنها لغة نموذجية ، إلا أن JSX هو في الواقع مجرد بناء جملة أو سكر نحوي ، إذا أردت ، في مكالمات React ، تشبه إلى حد كبير HTML.

تم تنظيم ملفات HTML الخاصة بنا بشكل جيد ، وتم إجراء معظم عمليات العرض الخاصة بنا ببساطة مثل template.render() . كيف يمكننا الاحتفاظ بهذا الترتيب والبساطة أثناء الانتقال إلى React؟ بالنسبة لي ، بصرف النظر عن الصعوبات التقنية ، كانت فكرة واحدة واضحة: استبدل مكالماتنا الحالية برمز JSX.

الصورة


بعد بعض التخطيط الأولي ، أعطيته أداة "سطر الأوامر" التي اختتمت تنفيذ أمرين بسيطين:

  1. يقرأ القوالب المشار إليها في ملف واجهة المستخدم (JavaScript)
  2. استبدل مكالمات template.render() بمحتوى HTML

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

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

الصورة


حسنًا ، بعد عدة أيام وُلدت أداة لتحويل قوالب Dust.js المشابهة لـ HTML إلى رمز JSX React . استخدمنا Dust ، لكن مع توفر عدد كبير من المحللون ، يجب أن تكون العملية مماثلة لترجمة أي لغة أخرى معروفة.

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

 <div class="encounters {?isExpanded}is-expanded{/isExpanded}"> {?showTooltip} <div class="tooltip"> <span>{#_t}{encounters_tooltip}{/_t}</span> <div class="icon"> {@Icon name="icon-encounters" size="stretch" /} </div> </div> {/showTooltip} <div class="images"> {#images} <img src="{src}"> <input type="radio" id="{id}" {?selected}checked{/selected} /> <label for="showme-{id}"> {name} </label> {/images} </div> <div class="footer"> {! encounters-footer template will be injected here !} </div> </div> 

إلى مكافئ كود JSX الخاص به:

 <div className="encounters {props.isExpanded ? 'is-expanded' : ''}"> {props.showTooltip ? <div className="tooltip"> <span>{i18n.get('encounters_tooltip')}</span> <div className="icon"> <Icon name="icon-encounters" size="stretch" /> </div> </div> : null} <div className="images"> {props.images.map(item => <img src={item.src}> <input type="radio" id={`showme-${item.id}`} defaultChecked={item.selected ? true : undefined} /> <label htmlFor={`showme-${item.id}`}> {item.name} </label> )} </div> <div className="footer"> {/* encounters-footer template will be injected here */} </div> </div> 

انظر مقارنة جنبا إلى جنب هنا .

بعد ذلك ، كانت عمليتنا واضحة إلى حد كبير. قمنا تلقائيًا بتحويل القوالب الخاصة بنا من تنسيق إلى آخر ، وعمل كل شيء كما هو متوقع (شكرًا لك ، الاختبار التلقائي). بادئ ذي بدء ، حافظنا على API template.render() القديمة الخاصة بنا للحفاظ على التغييرات معزولة.

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

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



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

مع ظهور ES7 / 8 / Next ، Elm و Reason ، ناهيك عن TypeScript والحلول المشابهة ، أصبح الكود الذي كان مرة واحدة *.js يتعذر تمييزه أكثر فأكثر من JavaScript ، ويبدو أن هذا الاتجاه سيستمر. بدلاً من أن تطغى عليها ، لماذا لا تستخدم هذا لصالحنا؟

المصدر المفتوح


انطلاقًا من عمل شيء واحد جيدًا ، قمنا ببناء هذه الأدوات الداخلية في عدة أجزاء:

  1. dust2jsx - الحزمة المسؤولة عن الترجمة الفعلية للغبار إلى jsx
  2. ratt (React All The Things) - أداة سطر الأوامر لقراءة / كتابة الملفات على القرص. مسؤول عن تضمين القوالب المرجعية ، ويستخدم dust2jsx داخليًا لتحويل الشفرة

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

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


All Articles