Bevorstehende Kernänderungen, die einige Themes/Komponenten beeinträchtigen könnten (12. April)

Nächste Woche werde ich diesen PR zusammenführen, der es Themes und Komponenten ermöglicht, QUnit-Tests zu haben. Dabei wird jedoch auch die Art und Weise geändert, wie Discourse JavaScript in Themes verarbeitet/transpiliert. Diese Änderungen rückwärtskompatibel umzusetzen, ist sehr schwierig, ohne viel Code im Kern neu zu gestalten (was wiederum andere nicht-rückwärtskompatible Änderungen mit sich bringen könnte). Daher können diese Änderungen beim Upgrade Ihrer Site das JavaScript Ihrer Themes/Komponenten beschädigen.

In diesem Beitrag erkläre ich, welche Änderungen Ihre Themes/Komponenten betreffen könnten und was Sie tun müssen, um sie zu beheben.

1. JavaScript innerhalb von <script type="text/discourse-plugin">-Tags wird mit aktiviertem Strict Mode ausgeführt

Diese Änderung betrifft keinen JS-Code, der nicht innerhalb von <script type="text/discourse-plugin">-Tags steht. Wenn Ihr Code in regulären <script>-Tags oder in eigenständigen .js-Dateien enthalten ist, sind Sie vor dieser Änderung völlig sicher.

Der einfachste Weg, um festzustellen, ob Ihr Theme oder Ihre Komponente von dieser Änderung betroffen ist, besteht darin, Ihren JS-Code in einen Immediately-Invoked Function Expression (IIFE) zu verpacken und oben in Ihrem Code "use strict"; hinzuzufügen. Nehmen wir an, Ihr Themes-Code sieht derzeit so aus:

<script type="text/discourse-plugin" version="0.8.11">
  a = 5;
  console.log(a);
</script>

Nachdem Sie ihn in ein IIFE verpackt haben, sollte er so aussehen ("use strict"; ist wichtig, da es den Strict Mode aktiviert und wir testen möchten, wie sich unser Code im Strict Mode verhält):

<script type="text/discourse-plugin" version="0.8.11">
  (function() {
    "use strict";
    a = 5;
    console.log(a);
  })();
</script>

Wenn Ihre Komponente nach diesem Schritt nicht mehr funktioniert, wird sie beim Upgrade Ihrer Site brechen. Um Ihren Code zu reparieren, empfehle ich dringend, zuerst die MDN-Dokumentation für den JavaScript Strict Mode zu lesen und dann zu prüfen, ob Ihr Theme/die Komponente etwas tut, das im Strict Mode verboten ist. Falls ja, müssen Sie Ihren Code so umgestalten, dass er nichts Verbotenes mehr tut.

Der wahrscheinlichste Fehler, den Sie sehen werden, ist ein ReferenceError beim Deklarieren einer Variable ohne das Schlüsselwort var (oder let/const). Im obigen Beispiel wirft die Zeile a = 5; unter Strict Mode eine ReferenceError-Ausnahme, weil wir vergessen haben, var hinzuzufügen. Der Code sieht nach der Korrektur so aus:

<script type="text/discourse-plugin" version="0.8.11">
  (function() {
    "use strict";
    var a = 5;
    console.log(a);
  })();
</script>

Sobald Sie mit dem Testen/Beheben Ihres Codes fertig sind, können Sie das IIFE und die Zeile "use strict"; problemlos entfernen.

2. Die Pfade zu JavaScript-Modulen in Themes werden mit Theme-IDs vorangestellt.

Vor einiger Zeit haben wir eine neue Funktion eingeführt, die es ermöglicht, JavaScript in Themes in mehrere Dateien aufzuteilen. Um die bevorstehende Änderung zu erklären, muss ich etwas Kontext zu dieser Funktion geben.

Wenn ein Theme/eine Komponente, die eigenständige JavaScript-Dateien enthält, auf einer Discourse-Instanz installiert wird, durchläuft Discourse alle JavaScript-Dateien und erstellt für jede eine JavaScript-Modul. Jedes Modul benötigt eine eindeutige Kennung (bzw. Pfad), daher verwendet Discourse den Dateipfad (mit geringfügigen Änderungen) als Pfad des Moduls.

Wenn Ihr Theme/eine Komponente beispielsweise eine Datei unter javascripts/discourse/helpers/my-helper.js hat, erstellt Discourse ein Modul für diese Datei und weist discourse/helpers/my-helper als Pfad zu. Das Modul enthält dann eine transpilierte Version des JavaScripts aus der ursprünglichen Datei.

Das Schöne an Modulen ist, dass Sie Klassen/Funktionen/Objekte usw. aus einem Modul in ein anderes importieren können. Beispielsweise könnten Sie eine Funktion namens xyz aus my-helper in andere Module importieren, indem Sie eine import-Anweisung wie folgt verwenden:

// javascripts/discourse/controllers/my-theme-controller.js

import { xyz } from "discourse/helpers/my-helper";

Der PR, den ich nächste Woche zusammenführen werde, fügt einen Präfix zu den Pfaden der Theme-Module hinzu. In unserem Beispiel ändert sich my-helper also von discourse/helpers/my-helper zu discourse/theme-<theme_id>/helpers/my-helper. Das bedeutet, dass unsere import-Anweisung nicht mehr funktioniert, da sich der Modulpfad geändert hat. Um dies zu beheben, müssen wir den Pfad in der import-Anweisung einfach von absolut auf relativ ändern, wie folgt:

// javascripts/discourse/controllers/my-theme-controller.js

import { xyz } from "../helpers/my-helper";

Jetzt sollte unsere import-Anweisung wieder funktionieren. Sehen Sie sich diese PRs 1 und 2 für echte Beispiele von Komponenten an, die von Punkt (2) betroffen sind, und wie sie behoben wurden.

Nochmals: Dies betrifft Ihr Theme/Ihre Komponente nur, wenn es/sie aus einem seiner eigenen Module importiert; das Importieren von Kernmodulen ist von dieser Änderung nicht betroffen.

Ich hoffe, das hilft. Falls Sie Fragen haben, lassen Sie es mich bitte wissen!

31 „Gefällt mir“

Vielen Dank für die detaillierte Zusammenfassung :slight_smile:

Betrifft dies „absolute

7 „Gefällt mir“

Ja, das ist korrekt :+1:

6 „Gefällt mir“

@loginerror, ich denke, du wirst dieses Thema nützlich finden :wink:

7 „Gefällt mir“

@Terrapop
Ich glaube, du hattest Bedenken dazu.

5 „Gefällt mir“

Wir haben unseren Code bereits korrigiert, als dies für eine begrenzte Zeit bereitgestellt wurde.

5 „Gefällt mir“