JSX à la place de la fonction h (createElement) dans les widgets et ailleurs

Bonjour, j’ai expérimenté l’utilisation de JSX dans les widgets pour améliorer l’expérience développeur dans les thèmes (j’ai mis au point ma propre configuration pour le développement de thèmes sans header.html, etc., je reviendrai là-dessus dans un autre sujet).

Je me demandais pourquoi Discourse n’utilise pas les plugins Babel dans sa base de code. Dans Discourse, le plugin Babel transform-react-jsx est disponible et peut être utilisé pour transformer le JSX en une fonction createElement personnalisée grâce à l’option jsxPragma. Tout cela est disponible dans Discourse.

L’ajout de transform-react-jsx ici https://github.com/discourse/discourse/blob/master/lib/discourse_js_processor.rb#L143-L149 et l’exposition d’une configuration Babel permettant de modifier le jsxPragma ici https://github.com/discourse/discourse/blob/master/vendor/assets/javascripts/babel.js
pourrait rendre cela possible.

J’ai déjà implémenté la première partie ; la partie pragma nécessite encore quelques investigations. Malheureusement, il n’y a pas de fichier .babelrc pour configurer individuellement les plugins. J’obtiens la fonction React.createElement au lieu de la fonction personnalisée.

Plus d’informations sur l’utilisation de JSX sans React ici : Using jsx WITHOUT React | r0b blog

Des idées ou peut-être de l’aide pour savoir comment cela pourrait être réalisé ?

MISE À JOUR :
J’ai réussi à faire fonctionner cela en modifiant le paramètre pragma dans vendor/assets/javascripts/babel.js à la ligne 26586 :

var id = state.opts.pragma || "React.createElement";
// à
var id = state.opts.pragma || "h";

Avez-vous vu ceci ? Vous pouvez désormais utiliser des modèles si vous n’aimez pas Hyperscript :

4 « J'aime »

@merefield oui, je connais hbs, mais je ne suis pas un « développeur de thème Discourse typique » :slight_smile:. Je souhaite exploiter la puissance de JSX, qui est du véritable JavaScript, plutôt que d’utiliser hbs, dont les fonctionnalités sont limitées.

J’ai réussi à utiliser JSX dans un thème Discourse maintenant. Mais dans ma propre fork de Discourse, donc ce n’est pas très utile pour le développement de thèmes en général.

2 « J'aime »

Finalement, c’est à @eviltrout de décider. Je peux cependant vous donner mon avis. Oui, JSX peut être agréable à utiliser et nous pourrions l’intégrer dans Discourse, mais je ne pense pas que nous le fassions, car nous devrions le prendre en charge et nous sommes plutôt orientés vers la suppression des widgets à terme que vers l’ajout de nouvelles options.

9 « J'aime »

Je comprends tout à fait votre point de vue. Je me demande juste pourquoi ne pas ouvrir la configuration de Babel (et de beaucoup d’autres choses) aux développeurs de thèmes et de plugins ?

Par exemple, un fichier .babelrc dans le dossier du thème pourrait être utilisé pour ajouter des options supplémentaires au transpileur JavaScript. Si .babelrc est présent, discourse_js_processor pourrait l’utiliser, étendre sa configuration Babel et activer de nombreuses fonctionnalités JavaScript supplémentaires.

C’est juste une idée.

C’est simplement une question d’« API publique » au sens large : tout ce que nous autorisons, nous devrons le prendre en charge. Ce qui semble facile à supporter aujourd’hui pourrait s’avérer difficile demain. Nous expérimentons actuellement de nombreuses choses en cours de développement, notamment du côté client de l’application. Voyons ce que Robin en pense.

5 « J'aime »

Ne vous sentez surtout pas obligé, je suis simplement un développeur curieux avec quelques questions. Je viens de l’univers du JavaScript full stack (Node/Vue), où Ember n’est tout simplement pas une option, surtout quand on a React ou, encore mieux, Vue.

Ember semble tellement contre-nature et handlebars est tout simplement dépassé en termes de fonctionnalités. La puissance de templating de JSX et surtout des SFC Vue ne peut pas être comparée à quelque chose d’aussi basique que hbs.

2 « J'aime »

Je ne suis pas d’accord pour dire qu’Ember n’est pas une option pour le JavaScript full stack. Je comprends l’argument selon lequel Ember est moins populaire que d’autres frameworks et que vous pourriez préférer en choisir un autre pour cette raison, mais il existe certainement de nombreux sites utilisant Node en back-end et Ember en front-end. Après tout, tous les outils d’Ember sont basés sur Node.

Cela dit, JSX n’est pas prévu dans le cœur de Discourse à l’avenir, mais s’il y a des choses que nous pourrions faire pour permettre son utilisation dans les plugins, je serais ouvert à l’idée. Veuillez soumettre une proposition expliquant comment cela fonctionnerait !

9 « J'aime »

C’est une option, mais dans mon contexte de développement et de travail autour de cela, ce n’est pas le cas, et personnellement, je ne l’utiliserais pas car Vue semble être un choix naturel pour ce type d’applications.

Juste un peu de contexte :

Ces derniers mois, j’ai travaillé sur le développement d’un thème assez personnalisé pour un client, ce qui m’a permis d’apprendre pas mal de choses sur le fonctionnement interne de Discourse, mais c’est probablement un petit pourcentage.

Actuellement, je suis en train de refactoriser un certain nombre d’erreurs de débutant et j’essaie de rendre les choses aussi conviviales que possible pour les futurs collègues qui pourraient se retrouver à maintenir mon travail. C’est pourquoi j’ai fait quelques expériences concernant JSX.

Aujourd’hui, j’ai essayé l’approche du premier message du sujet. J’ai inclus transform-react-jsx ici : 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

Et j’ai modifié le paramètre pragma dans vendor/assets/javascripts/babel.js à la ligne 26586 :

var id = state.opts.pragma || "React.createElement";
// vers
var id = state.opts.pragma || "h";

Cela m’a permis d’utiliser la fonction h de virtual-dom au lieu de React.createElement dans le code transformé par Babel. h fait partie de Discourse et cela semblait être un choix naturel.

Je ne connais pas l’histoire du développement de Discourse, et vous avez probablement vos raisons d’avoir ajouté un fichier babel.js complet avec une série de plugins utiles dans le code. C’est dommage que ces plugins ne soient pas disponibles pour les développeurs utilisateurs comme moi. Ma proposition serait donc de :

  1. Utiliser une sorte de configuration Babel, .babelrc, .babel.yml, ou définir un champ de configuration Babel dans about.json comme dans package.json Configure Babel · Babel. Cette configuration pourrait référencer tous ces plugins dans babel.js (ou peut-être d’autres, voir point 3).

  2. Dans discourse_js_processor.rb#babel_parse https://github.com/discourse/discourse/blob/master/lib/discourse_js_processor.rb#L138, lire cette configuration et l’étendre à la configuration actuelle.

  3. Si un développeur souhaite avoir un plugin Babel personnalisé, il pourrait l’ajouter à son dossier vendor/assets/javascripts/babel/plugins (ou simplement au dossier babel/plugins) et Discourse le détecterait et l’utiliserait dans le processus de transpilation.

Je n’ai pas d’expérience dans le développement backend Rails, donc c’est ma méta-proposition.

Et une autre question, puisque nous y sommes, à quel point serait-il difficile pour Discourse de lire les dépendances depuis, disons, le fichier package.json des thèmes, de les installer au premier lancement et de les utiliser (en les mettant en cache ou quelque chose comme ça) à l’intérieur du thème ? (Si les dépendances changent, vérifier lesquelles ont changé et les installer ou les supprimer, etc.).

Une fois de plus, vous faites un excellent travail et votre travail est incroyable. Veuillez ne pas ressentir de pression de ma part, je suis simplement ici pour apprendre, avoir de bonnes discussions et partager des opinions et des idées. Je n’attends pas de vous que vous mettiez en œuvre mes demandes ou quoi que ce soit.

3 « J'aime »

Que voulez-vous dire par là ? Qu’est-ce qui n’est pas possible avec Handlebars et Ember et qui est implémenté dans un autre framework ?

Ce que je voulais dire, c’est que JSX est du JavaScript, pas un langage de templating. Le fait d’être du JavaScript pur le rend plus puissant (par exemple : l’opérateur ternaire, la fonction map, etc.). Vous pouvez réaliser tout ce que vous voulez avec Ember/Handlebars, mais JSX est plus pratique et plus convivial pour les développeurs, à mon avis.

1 « J'aime »

Est-ce que cela a fonctionné ? Avez-vous pu ajouter du JSX et tout s’est bien passé ?

Maintenant, concernant les autres questions que vous aviez sur la raison pour laquelle Babel est configuré de cette manière : Discourse est construit sur Rails en utilisant le pipeline d’actifs, et la prise en charge de webpack n’a été ajoutée à Rails qu’à partir de la version 6. La base de code de Discourse a 8 ans ! Au fil du temps, nous y avons ajouté des fonctionnalités, mais nous avons dépassé ses limites.

L’un des grands projets de cette année est la migration vers Ember CLI — si vous examinez nos commits, vous verrez les travaux en cours pour atteindre cet objectif dans Discourse, mais c’est un long chemin.

Une fois cela en place, vous pourrez utiliser beaucoup plus de fonctionnalités de construction JavaScript qui ne fonctionnent actuellement que si vous les exécutez depuis Ruby, ce qui est fastidieux. En attendant, je ne vois pas comment nous pourrions consacrer du temps à la lecture de package.json et à son intégration automatique dans le pipeline Rails.

6 « J'aime »

Je vais préparer une PR de preuve de concept pour montrer comment cela fonctionne.

Merci pour ces éclaircissements et explications !

3 « J'aime »

Une mise à jour : j’ai réussi à créer un ThemeField Babel, qui sert à lire babel.config.json depuis le thème et à injecter des plugins dans Babel.transform au sein de discourse_js_processor.

J’espère pouvoir publier la PR bientôt, ne serait-ce que pour en faire une preuve de concept. Attention, ce sera un vrai fouillis :sweat_smile:.

PS. Ruby est si agréable à utiliser :star_struck:

Voici le lien :

2 « J'aime »