JavaScript in Themes und Komponenten asynchron laden

Dank @david haben wir ein sehr sauberes Muster für das „eager" Laden von JavaScript in Themes.

Das bedeutet, Sie platzieren einfach *.js.es6-Dateien im Verzeichnis javascripts, und es funktioniert exakt wie bei Plugins – das ist großartig.

So erstellen Sie beispielsweise jetzt einen Initialisierer, der zu 100 % mit Plugins übereinstimmt:

  • Erstellen Sie eine Datei namens /javascripts/discourse/initializers/my-init.js.es6
import { withPluginApi } from "discourse/lib/plugin-api";

function initialize(api) {
  // Init über API hier
}

export default {
  name: "discourse-otp",

  initialize() {
    withPluginApi("0.8.28", initialize);
  }
};

Dies ist eine enorm wichtige Funktion, da wir nun große, komplexe Themes in viele Teile aufteilen können, sowie Linting, Syntax-Highlighting und all die anderen Vorteile erhalten.

In einigen Fällen möchten wir jedoch ein JS-Payload optional bereitstellen.

Stellen Sie sich zum Beispiel vor, wir dekorieren Beiträge, aber nur Beiträge mit sehr spezifischem Markdown. Es hat keinen Sinn, eine 100 KB große, ausgefallene Bibliothek herunterzuladen, bis wir wissen, dass wir sie verwenden werden.

Ich habe dies in meiner Komponente mit folgender cleverer Änderung umgangen:

https://github.com/discourse/discourse/commit/719a93c312b9caa6c71de22d67f1ce1a78c1c8b2

Dazu:

import loadScript from "discourse/lib/load-script";

function generateOtp($elem) {
  loadScript(settings.theme_uploads.jsotp).then(() => {
     // Hier kommt der Code hin
  });
}

Das bedeutete:

  1. Ich musste .js zu den „theme authorized extensions" hinzufügen.
  2. Ich musste eine Umgehung für die CSP für das jeweilige Asset in „content security policy script src" hinzufügen.
  3. Ich musste das Asset in meiner about.json benennen.

Als Autor eines Theme-Components ist das einfach zu viel Hürde, da man im Verteilungswettbewerb keine Chance hat, wenn man dieses Niveau an Ninja-Fähigkeiten erfordert.

Ich denke, um dies nutzbar zu machen, gibt es zwei Alternativen, aus denen wir wählen können:

  1. Wir können das System so lehren, dass es die .js-Assets in aktiven Themes automatisch CSP-konform macht und standardmäßig Themes erlaubt, .js-Dateien hochzuladen.

  2. Wir können uns in Richtung etwas wie javascript_cache bewegen, das nicht verzögertes Theme-JS verwendet.

Ich tendiere eher zu Option 1, da das Hinzufügen von .js zu den autorisierten Theme-Erweiterungen trivial erscheint und eine automatische CSP-Einrichtung nicht unmöglich sein sollte.

@pmusaraj / @Johani / @Osama, habt ihr dazu Gedanken?

10 „Gefällt mir“

The ability to reference theme uploads in JS is a great addition! :100:

This makes a lot of sense to me because anything you can do in a .js file can already be done in files in the javascripts folder of the theme. So, I don’t see any harm in allowing themes to have .js uploads by default.

7 „Gefällt mir“

Wiederbelebung, da das Einzige, was hier noch zu tun ist, ist, CSP beizubringen, js-Uploads für Themes zuzulassen. js-Dateien sind seit einiger Zeit standardmäßig für Theme-Uploads erlaubt.

Wenn Theme-js-Uploads nicht durch CSP blockiert werden, müssen Komponenten wie Image Annotator - Allows you to annotate images in the previewer ihre Abhängigkeiten nicht auf der Homepage laden (~170 KB gzip). Diese Komponente müsste beispielsweise diese Abhängigkeiten nur laden, wenn der Composer geöffnet wird. Außerdem muss sie sie niemals für anonyme Betrachter laden.

Außerdem würde diese Änderung Themes erlauben, Web-Worker-Dateien (Web Workers API) zu haben, die einige schwere Aufgaben außerhalb des Hauptthreads erledigen können.

Erlauben in Anführungszeichen oben, da Sie sie als Blobs haben können, aber es ist viel schöner, sie in separaten Dateien zu haben, anstatt mit JavaScript in einem String herumzuspielen.

4 „Gefällt mir“

Ich habe hier eine gute Nachricht: Es ist etwas knifflig zu implementieren, aber endlich werden wir lokale JS-Assets unterstützen, wenn wir Web Worker in Theme-Komponenten verwenden wollen.

Es gibt keinen anderen sauberen Weg, dies durch die CSP zu bekommen. Das Ausliefern von Worker-Dateien von derselben Domain schließt hier die riesige Lücke.

3 „Gefällt mir“

Hinweis… das wurde jetzt ausgeliefert :confetti_ball:

5 „Gefällt mir“