La semaine prochaine, je vais fusionner cette PR qui permet aux thèmes et composants d’avoir des tests QUnit. Cependant, cela modifie également la manière dont le JavaScript des thèmes est traité/transpilé par Discourse. Rendre ces changements rétrocompatibles est très difficile sans réécrire une grande partie du code principal (ce qui pourrait d’ailleurs introduire d’autres changements non rétrocompatibles). Par conséquent, ces modifications pourraient casser le JavaScript de vos thèmes ou composants lors de la mise à niveau de votre site.
Dans cet article, je vais expliquer quels sont les changements susceptibles d’affecter vos thèmes ou composants et ce que vous devez faire pour les corriger.
1. Le JavaScript à l’intérieur des balises <script type="text/discourse-plugin"> sera exécuté avec le mode strict activé
Ce changement n’affecte pas le code JS qui ne se trouve pas dans des balises <script type="text/discourse-plugin">. Vous êtes totalement à l’abri de ce changement si votre code se trouve dans des balises <script> classiques ou dans des fichiers .js autonomes.
La façon la plus simple de savoir si votre thème ou composant est affecté par ce changement consiste à envelopper votre code JS dans une Expression de Fonction Exécutée Immédiatement (IIFE) et à ajouter "use strict"; au début de votre code. Par exemple, supposons que votre code de thème ressemble actuellement à ceci :
<script type="text/discourse-plugin" version="0.8.11">
a = 5;
console.log(a);
</script>
Après l’avoir enveloppé dans une IIFE, il devrait ressembler à ceci ("use strict"; est important car il active le mode strict et nous voulons tester le comportement de notre code en mode strict) :
<script type="text/discourse-plugin" version="0.8.11">
(function() {
"use strict";
a = 5;
console.log(a);
})();
</script>
Si votre composant cesse de fonctionner après avoir effectué cette opération, il se cassera lors de la mise à niveau de votre site. Pour corriger votre code, je vous recommande vivement de lire d’abord la documentation MDN sur le mode strict de JavaScript, puis de vérifier si votre thème ou composant effectue une action interdite en mode strict. Si c’est le cas, vous devez refactoriser votre code pour qu’il n’effectue aucune action interdite.
L’erreur la plus probable que vous rencontrerez est une ReferenceError lors de la déclaration d’une variable sans le mot-clé var (ou let/const). Dans l’exemple ci-dessus, la ligne a = 5; lancera une exception ReferenceError en mode strict car nous avons oublié d’ajouter var. Le code ressemble à ceci une fois corrigé :
<script type="text/discourse-plugin" version="0.8.11">
(function() {
"use strict";
var a = 5;
console.log(a);
})();
</script>
Une fois que vous avez terminé les tests et la correction de votre code, vous pouvez librement supprimer l’IIFE et la ligne "use strict";.
2. Les chemins des modules JavaScript des thèmes seront préfixés par les identifiants des thèmes.
Il y a quelque temps, nous avons ajouté une nouvelle fonctionnalité permettant de diviser le JavaScript des thèmes en plusieurs fichiers. Je dois fournir un peu de contexte sur cette fonctionnalité pour expliquer le changement à venir.
Lorsqu’un thème ou composant livré avec des fichiers JavaScript autonomes est installé sur une instance Discourse, Discourse parcourt tous les fichiers JavaScript et crée un module JavaScript pour chacun d’eux. Chaque module doit avoir un identifiant unique (c’est-à-dire un chemin), donc Discourse utilise le chemin du fichier (avec de légères modifications) comme chemin du module.
Par exemple, si votre thème ou composant possède un fichier à l’adresse javascripts/discourse/helpers/my-helper.js, Discourse créera un module pour ce fichier et attribuera discourse/helpers/my-helper comme chemin, et le module contiendra une version transpilée du JavaScript contenu dans le fichier original.
L’avantage des modules est que vous pouvez importer des classes/fonctions/objets, etc., d’un module vers un autre. Par exemple, vous pouvez importer une fonction appelée xyz depuis my-helper vers d’autres modules en utilisant une instruction import comme suit :
// javascripts/discourse/controllers/my-theme-controller.js
import { xyz } from "discourse/helpers/my-helper";
La PR que je vais fusionner la semaine prochaine ajoutera un préfixe aux chemins des modules des thèmes. Ainsi, dans notre exemple, my-helper passera de discourse/helpers/my-helper à discourse/theme-<theme_id>/helpers/my-helper. Cela signifie que notre instruction import cessera de fonctionner car le chemin du module aura changé. Pour le corriger, nous devons simplement changer le chemin dans l’instruction import d’absolu à relatif comme suit :
// javascripts/discourse/controllers/my-theme-controller.js
import { xyz } from "../helpers/my-helper";
Et maintenant, notre instruction import devrait fonctionner à nouveau. Consultez ces PR 1 et 2 pour des exemples réels de composants affectés par le point (2) et la manière dont ils ont été corrigés.
Encore une fois, cela n’affecte votre thème ou composant que s’il importe depuis l’un de ses propres modules ; l’importation de modules principaux n’est pas affectée par ce changement.
J’espère que cela vous aidera. Si vous avez des questions, n’hésitez pas à me le faire savoir !