JSX بدلاً من دالة h (createElement) في العناصر البرمجية وأماكن أخرى

مرحبًا، لقد كنت أجرب JSX في الودجات لتحسين تجربة المطورين في السمات (لقد طورت إعداداتي الخاصة لتطوير السمات دون استخدام header.html وما إلى ذلك، وسأفصل ذلك أكثر في موضوع آخر).

تساءلت لماذا لا يستفيد Discourse من إضافات Babel داخل قاعدة شفرته. في Discourse، يتوفر إضافة transform-react-jsx التي يمكن استخدامها لتحويل JSX إلى دالة createElement مخصصة باستخدام خيارات jsxPragma. كل ذلك متاح في Discourse.

يمكن تحقيق ذلك بإضافة transform-react-jsx هنا https://github.com/discourse/discourse/blob/master/lib/discourse_js_processor.rb#L143-L149، وبطريقة ما عرض إعدادات Babel لتغيير jsxPragma هنا https://github.com/discourse/discourse/blob/master/vendor/assets/javascripts/babel.js.

لقد نفذت الجزء الأول بالفعل، لكن جزء الـ pragma لا يزال يحتاج إلى بعض الاستكشاف. للأسف، لا يوجد ملف .babelrc لإعداد تكوين كل إضافة على حدة. أحصل على دالة React.createElement بدلاً من الدالة المخصصة.

لمزيد من التفاصيل حول استخدام JSX بدون React، راجع: Using jsx WITHOUT React | r0b blog

هل لديك أي أفكار أو ربما مساعدة حول كيفية تحقيق ذلك؟

تحديث:
تمكنت من جعل هذا يعمل عن طريق تغيير إعداد الـ pragma في vendor/assets/javascripts/babel.js في السطر 26586:

var id = state.opts.pragma || "React.createElement";
// إلى
var id = state.opts.pragma || "h";

هل رأيت هذا؟ يمكنك الآن استخدام القوالب إذا لم يعجبك Hyperscript:

4 إعجابات

@merefield نعم، أنا على علم بـ hbs، لكنني لست “مطور مواضيع ديسكورد نموذجيًا” :slight_smile:. أرغب في استخدام قوة JSX، وهي جافا سكريبت فعلية، بدلاً من hbs التي تكون محدودة في وظائفها.

وقد تمكنت من استخدام JSX في موضوع ديسكورد الآن. لكن في نسخة ديسكورد الخاصة بي، لذا فهي ليست مفيدة جدًا لتطوير المواضيع بشكل عام.

إعجابَين (2)

في النهاية، القرار يعود إلى @eviltrout. مع ذلك، يمكنني أن أعبر عن رأيي. نعم، يمكن أن يكون JSX ممتعًا في الاستخدام، وقد ندرجه في Discourse، لكنني لا أعتقد أننا سنقوم بذلك، لأننا سنضطر إلى دعمه، ونحن نميل أكثر إلى التخلص من الودجات (widgets) في مرحلة ما بدلاً من إضافة المزيد من الخيارات.

9 إعجابات

أفهم وجهة نظرك تمامًا. أتساءل فقط، لماذا لا نفتح إعدادات Babel (وجميع الأشياء الأخرى) لمطوري السمات والإضافات؟

على سبيل المثال، يمكن استخدام ملف .babelrc الموجود في مجلد السمة لبعض الخيارات الإضافية لمترجم الجافا سكريبت. إذا كان ملف .babelrc موجودًا، فيمكن لـ discourse_js_processor استخدامه وتوسيع إعدادات Babel الخاصة به لتمكين مجموعة إضافية من ميزات الجافا سكريبت.

فقط فكرة.

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

5 إعجابات

لا تشعر بأي ضغط، فأنا مجرد مطور فضولي لديه بعض الأسئلة. لقد جئت إلى Discourse من عالم JavaScript كامل المكدس (Node/Vue) حيث لا يُعد Ember خيارًا، خاصةً عندما يتوفر لديك React أو حتى Vue الذي هو أفضل.

يبدو Ember غير طبيعي، وhandlebars عفا عليها الزمن من حيث ميزاتها. لا يمكن مقارنة قوة القوالب في JSX وخصوصًا ملفات SFC الخاصة بـ Vue مع شيء أساسي مثل hbs.

إعجابَين (2)

أنا لا أوافق على أن Ember ليس خيارًا لتطبيقات JavaScript الكاملة (full stack). أفهم الحجة القائلة بأن Ember ليس شائعًا مثل أطر العمل الأخرى، وقد ترغب في اختيار إطار عمل آخر لهذا السبب، ولكن هناك بالتأكيد العديد من المواقع التي تستخدم Node في الخلفية وEmber في الواجهة الأمامية. فجميع أدوات Ember مبنية على Node، في النهاية.

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

9 إعجابات

إنه خيار، لكن في سياق تطوري وعملي، لا يُعد خيارًا عمليًا، ولا أستخدمه شخصيًا لأن Vue يبدو مناسبًا بشكل طبيعي لمثل هذه التطبيقات.

بعض السياق فقط:

خلال الأشهر القليلة الماضية، كنت أعمل على تطوير سمة (Theme) مخصصة للغاية لعميل، حيث تعلمت الكثير حول الآليات الداخلية لـ Discourse، لكن هذا على الأرجح يمثل نسبة صغيرة فقط.

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

اليوم، جربت النهج المذكور في المنشور الأول في الموضوع. لقد قمت بتضمين transform-react-jsx هنا: https://github.com/discourse/discourse/blob/master/lib/discourse_js_processor.rb#L143-L149:

      if opts[:module_name] && !@skip_module
        filename = opts[:filename] || 'unknown'
        "Babel.transform(#{js_source}, { moduleId: '#{opts[:module_name]}', filename: '#{filename}', ast: false, presets: ['es2015'], plugins: [['transform-es2015-modules-amd', {noInterop: true}], 'transform-decorators-legacy', 'transform-react-jsx', exports.WidgetHbsCompiler] }).code"
      else
        "Babel.transform(#{js_source}, { ast: false, plugins: ['check-es2015-constants', 'transform-es2015-arrow-functions', 'transform-es2015-block-scoped-functions', 'transform-es2015-block-scoping', 'transform-es2015-classes', 'transform-es2015-computed-properties', 'transform-es2015-destructuring', 'transform-es2015-duplicate-keys', 'transform-es2015-for-of', 'transform-es2015-function-name', 'transform-es2015-literals', 'transform-es2015-object-super', 'transform-es2015-parameters', 'transform-es2015-shorthand-properties', 'transform-es2015-spread', 'transform-es2015-sticky-regex', 'transform-es2015-template-literals', 'transform-es2015-typeof-symbol', 'transform-es2015-unicode-regex', 'transform-regenerator', 'transform-decorators-legacy', 'transform-react-jsx',exports.WidgetHbsCompiler] }).code"
      end

وتغيير إعداد الـ pragma في vendor/assets/javascripts/babel.js في السطر 26586

var id = state.opts.pragma || "React.createElement";
// إلى
var id = state.opts.pragma || "h";

هذا سمح لي باستخدام الدالة h من virtual-dom بدلاً من React.createElement في الكود الذي تمت معالجته بواسطة Babel. الدالة h جزء من Discourse، وشعرت أن هذا مناسب بشكل طبيعي.

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

  1. استخدام نوع من ملفات إعدادات Babel، مثل .babelrc أو .babel.yml، أو تحديد حقل إعدادات Babel في about.json كما هو الحال في package.json Configure Babel · Babel. يمكن لهذا الملف المرجعي أن يشير إلى جميع هذه الإضافات في babel.js (أو ربما إضافات أخرى، انظر النقطة 3).

  2. في discourse_js_processor.rb#babel_parse https://github.com/discourse/discourse/blob/master/lib/discourse_js_processor.rb#L138، قم بقراءة هذا الملف وقم بدمجه مع الإعدادات الحالية.

  3. إذا أراد المطور إضافة إضافة Babel مخصصة، فيمكنه إضافتها إلى مجلد vendor/assets/javascripts/babel/plugins الخاص به (أو مجلد babel/plugins ببساطة)، وسيتم التقاطها من قبل Discourse واستخدامها في عملية الترجمة.

لست خبيرًا في تطوير الواجهة الخلفية (Backend) باستخدام Rails، لذا هذا هو مقترحي العام.

وسؤال آخر، بينما نحن بصدد الحديث، ما مدى صعوبة قيام Discourse بقراءة التبعيات من ملف package.json الخاص بالسمات مثلاً، وتثبيتها عند التشغيل الأول، واستخدامها (تخزينها مؤقتًا أو ما شابه) داخل السمة؟ (إذا تغيرت التبعيات، تحقق من المتغير منها وقم بتثبيتها أو إزالتها، إلخ).

مرة أخرى، أنتم تقومون بعمل رائع وعملكم مذهل. من فضلكم، لا تشعروا بأي ضغط من جانبي، أنا هنا فقط للتعلم وللمشاركة في مناقشة جيدة وتبادل الآراء والأفكار. لا أتوقع منكم تنفيذ طلبيات أو أي شيء آخر.

3 إعجابات

ماذا تقصد بذلك؟ ما الذي لا يمكن تحقيقه باستخدام handlebars و Ember وهو مُطبَّق في إطار عمل آخر؟

ما أعنيه هو أن JSX هو JavaScript وليس لغة قوالب، وبكونه JavaScript بحد ذاته يصبح أكثر قوة (على سبيل المثال: العامل الثلاثي، دالة map، إلخ). يمكنك فعل ما تريد في Ember/Handlebars، لكن JSX أكثر ملاءمة وسهولة للمطورين، وذلك برأيي الشخصي.

إعجاب واحد (1)

وهل نجح ذلك؟ هل تمكنت من إضافة JSX وكل شيء على ما يرام؟

أما بالنسبة للأسئلة الأخرى التي كانت لديك حول سبب إعداد Babel بهذه الطريقة، فإليك التوضيح: تم بناء Discourse على Rails باستخدام خط أنابيب الأصول (asset pipeline)، ولم تتم إضافة دعم webpack إلى Rails إلا في الإصدار 6. إن قاعدة كود Discourse عمرها 8 سنوات! لذا، مع مرور الوقت، قمنا بإضافة أشياء إليها، لكننا تجاوزنا حدودها.

واحد من المشاريع الكبرى هذا العام هو الترحيل إلى Ember CLI - إذا نظرت إلى سجلات التعديلات (commits) لدينا، فستلاحظ العمل المتجه نحو هذا الهدف داخل Discourse، لكنه طريق طويل.

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

6 إعجابات

سأقوم بإنشاء طلب سحب تجريبي (POC PR) لإظهار كيفية عمل ذلك.

شكرًا لك على البصيرة والشرح!

3 إعجابات

تحديث - لقد تمكّنت من إنشاء ThemeField babel، والذي يُستخدم لقراءة babel.config.json من السمة (theme) وحقن الإضافات في Babel.transform داخل discourse_js_processor.

آمل أن أستطيع إصدار طلب السحب (PR) قريبًا لعرضه كمثال إثبات لمبدأ العمل. تحذير - سيكون الأمر فوضى كبيرة :sweat_smile:.

ملاحظة جانبية: Ruby سهلة جدًا في العمل معها :star_struck:

ها هو:

إعجابَين (2)