Probleme beim Laden eines JS-Assets aus einer Theme Component

Hallo, ich entwickle zum ersten Mal auf Discourse, daher entschuldige ich die dummen Fragen.
Ich baue eine Theme-Komponente, um PGNs (Schachbrett und Spiele) anzuzeigen.
Die Komponente ist theoretisch nicht schwierig, es gibt eine JS-Komponente dafür (PGNViewer.js) und ich konnte die [wrap]-Tags in die richtigen \u003cscript\u003evar x='pgn hier'; ...\u003c/script\u003e- und \u003cdiv class='pgn-blahblah'\u003e\u003c/div\u003e-Blöcke übersetzen.
Soweit so gut, aber jetzt muss ich das JS laden.
Ich habe festgestellt, dass ich import loadScript from \"discourse/lib/load-script\"; und await loadScript(settings.theme_uploads_local.pgnviewer_js); verwenden kann, um es zur Initialisierungszeit aus dem /assets/-Verzeichnis zu laden.
Aber hier habe ich ein paar Probleme.
Obwohl ich die Komponente auf der Entwicklungsinstallation laden kann, kann ich sie auf meinem Produktionsserver nicht laden, da sie besagt, dass die Asset zu groß ist. Gibt es eine Möglichkeit, dies zu beheben?
Zweitens sehe ich auf der Entwicklungsinstallation eine Warnung, dass /theme-javascripts/dist.js.map nicht geladen werden konnte. Ich habe keine Ahnung, woher das kommt. Muss ich etwas bereitstellen?
Ist dieser Ansatz insgesamt korrekt, oder wäre es besser, stattdessen ein Plugin zu implementieren?
Danke
Mit freundlichen Grüßen

FF

2 „Gefällt mir“

Willkommen bei Meta, @happycactus :wave:

Ja, wahrscheinlich. Der einzige Grund, warum Sie ein Plugin benötigen würden, ist, wenn Sie versuchen würden, die API (d. h. das Backend) zu ändern.

Ich hatte in der Vergangenheit ein ähnliches Problem.

Ja, Sie müssen app.yml ändern, um große Dateien über den Reverse-Proxy (nginx) zuzulassen.

Glücklicherweise ist dies eine einfache Einstellung, upload_size:, hier im Kontext:

params:
  ## Welche Git-Revision soll dieser Container verwenden? (Standard: tests-passed)
  version: tests-passed

  ## Maximale Upload-Größe (Standard: 10m)
  upload_size: 20m

Nachdem Sie dies geändert haben, müssen Sie neu erstellen, damit es wirksam wird:

./launcher rebuild app

Dies setzt natürlich voraus, dass Sie über entsprechenden Zugriff auf den Server verfügen …

2 „Gefällt mir“

Danke, Robert!

Ich bin mir unsicher, wahrscheinlich weil ich keine Erfahrung mit solchen Plattformen habe.
Mein Zweifel ist:

Mein Ansatz ist, den kleinen JavaScript-Schnipsel zu “embedden”, der benötigt wird, um den div-Block mit dem Inhalt zu füllen, aber ich sehe, dass ich ihn vielleicht aus einer Funktion “cookPgn” ausführen könnte, so wie es in der marmaid-Komponente geschieht:

async function applyMermaid(element, key = "composer") {
  const mermaids = element.querySelectorAll("pre[data-code-wrap=mermaid]");
  ...
  await loadScript(settings.theme_uploads_local.mermaid_js);
  ...
  mermaids.forEach((mermaid) => {
    if (mermaid.dataset.processed) {
      return;
    }

    const spinner = document.createElement("div");
    spinner.classList.add("spinner");
    ...
    mermaid.append(spinner);
  });

Auf diese Weise, wenn ich richtig verstehe, muss ich das Skript nicht von der Seite laden (vielleicht mit loadScript??), sondern kann es einfach in das Theme-JS importieren? Oder wahrscheinlich bin ich völlig auf dem Holzweg!
Ich meine, was ist der Unterschied zwischen loadScript und einem einfachen Import?
Können Sie mich auf eine Webressource verweisen, wo ich das besser verstehen kann?
Entschuldigen Sie nochmals, wenn die Fragen trivial oder dumm sind!

Eine andere Sache, das Limit ist standardmäßig auf 10M gesetzt, aber mein Asset ist etwa 300kb, und das gesamte Zip ist 337kb, trotzdem sagt es beim Hochladen, dass es mehr als 512kb ist.

Danke,

FF

Haben Sie einen Import versucht? Ich glaube nicht, dass Sie ein externes Skript importieren können.

Loadscript ist der richtige Ansatz und stellt sicher, dass das Skript vollständig geladen ist, bevor Ihr Code fortfährt und es verwendet (deshalb gibt es ein Promise zurück).

Können Sie die genaue Fehlermeldung mitteilen – ist dies in der Browserkonsole?

Ihr eigentliches Problem ist die Verwendung von Inline-JS, was durch CSP verboten ist.

Legen Sie diesen Code in eine Hilfsfunktion in Ihrem Theme-Komponenten-Code und fügen Sie ihn nicht in Beiträge ein.

Laden Sie Ihr aktuelles Theme auf GitHub hoch, damit wir es uns ebenfalls ansehen können.

5 „Gefällt mir“

Schauen Sie sich die Discourse Mermaid-Komponente an, die eine Bibliothek lädt und Dinge mit Beiträgen macht.

2 „Gefällt mir“

Danke, @Falco, das war einer meiner Zweifel.

Sicher, hier ist es: GitHub - studiofuga/discourse-pgn-component: A theme component for Discourse to display PGN blocks
Es gibt auch eine Plugin-Version, aber ich denke, ich werde diesen Ansatz nicht verfolgen und beim Theme-Komponenten bleiben.

Danke @pfaffman, tatsächlich habe ich mich davon inspirieren lassen und festgestellt, dass sie genau das tut, was ich brauche, und zwar auf die richtige Weise, ohne den Code wie oben vorgeschlagen einzufügen.

Danke an alle, ich werde eure Vorschläge ausprobieren und mich mit den Ergebnissen melden. Natürlich ist mein Code Open Source, daher ist jeder Beitrag oder jede Kritik sehr willkommen.

1 „Gefällt mir“

Mein Fehler, ich vergaß, dass ich die Anhangsgröße auf 512kB begrenzt hatte, erhöhte sie auf den Standardwert (4096) und es funktionierte gut. Danke und Entschuldigung für die dumme Frage.

2 „Gefällt mir“

Ok, ich habe alles behoben und die Komponente funktioniert! Aber wir haben ein Problem, ein “unsafe eval” in der Bibliothek, die ich benutze. Ich schätze, ich sollte die Upstream-Bibliothek reparieren, ich habe keine Ahnung, wie ich sie packen soll.
Für Interessierte, ich habe alle meine Änderungen in meinem obigen Repo hochgeladen, und hier sind die Details des Fehlers.

und die Zeile ist diese (im ursprünglichen js-Modul)

let isBrowser=new Function("try {return this===window;}catch(e){ return false;}")

hier.

1 „Gefällt mir“

Ihr Skript stolpert über die Content Security Policy in der Produktion.

Sie müssen 'unsafe-eval' als Eintrag in den Website-Einstellungen hinzufügen: content security policy script src

Danke, ich lese gerade die Dokumentation, um zu sehen, wie das geht. :slight_smile: Ich lerne viel, danke

1 „Gefällt mir“

Ok, ich habe es geschafft, nur ich musste ’ … lol… benutzen. Jedenfalls hat mein Skript fast funktioniert, ich habe alles auf main gepusht und es hat irgendwie funktioniert, es scheint, als hätte ich ein Problem mit dem Rendering, aber zumindest wird die Hauptkomponente aufgerufen (ich vermute, wo das Problem liegt).
Danke an alle… Ich bin bald wieder da mit mehr Fragen LOL. Danke!

1 „Gefällt mir“

Wenn man bedenkt, dass das Hinzufügen von unsafe-eval zu Ihrer CSP im Grunde den gesamten Sinn von CSP zunichtemacht und Ihre Website dadurch weniger sicher macht.

Die Verwendung von eval ist ein Code-Geruch und sollte, wie oben erwähnt, upstream behoben werden.

4 „Gefällt mir“

Ja, auf jeden Fall. Ich kann es im Moment nicht beheben, aber mein Plan ist es, zuerst meine Komponente zu reparieren, dann die Upstream-Bibliothek zu reparieren und die CSP-Überschreibung zu entfernen.
Danke für den Rat!

Ich bin fast fertig. Ich konnte „etwas“ anzeigen, aber es funktioniert zufällig.
Die von mir verwendete JS-Bibliothek funktioniert so:

Zuerst müssen wir einen <div>-Block mit einer eindeutigen ID definieren: <div id='board'>. Dann müssen wir eine Funktion aufrufen, um das Div zu füllen, so etwas wie: PGNV.pgnBoard('board', {});. Das Skript benötigt dieselbe ID, um es zu füllen.

Wenn ich das richtig verstehe, kann ich das nicht tun, während ich den „cooked block“ dekoriere, weil das Dokument noch nicht gefüllt ist und das PGNV-Objekt den Block nicht finden kann. Also habe ich zuerst ein Widget verwendet (funktioniert nicht, weil die HTML-Funktion den Block zurückgeben muss und ich ihn nicht habe), dann bin ich zu einer entprellten Funktion gewechselt: debounceFunction(this, renderPgn, attrs, 200);.

Aber es funktioniert „manchmal“.

Was übersehe ich?

Danke

debounceFunction verzögert den Aufruf der Zielmethode, bis der Debounce-Zeitraum ohne weitere Debounce-Aufrufe abgelaufen ist. Manchmal funktioniert er möglicherweise immer noch, weil

debounce ist möglicherweise nicht die Lösung für Ihren Anwendungsfall

Versuchen Sie, die Option afterAdopt zu verwenden

1 „Gefällt mir“

Hallo Hawn, danke für deinen Hinweis!
Es scheint genau das zu sein, wonach ich gesucht habe. Ich habe zwei verschiedene Ansätze ausprobiert:

  • Zuerst die normale „decorateCooked“-Funktion verwenden, um den Div-Block zu parsen und anzuhängen, und dann afterAdopt, um ihn durch Aufrufen von PGNV.pgnviewer() zu rendern, oder
  • nur die afterAdopt-Option verwenden, um sowohl anzuhängen als auch zu rendern

Keiner davon hat für ein weiteres Problem funktioniert, das ich noch nicht ganz verstehe. Anscheinend stürzt die interne Bibliothek mit einem Fehler ab, da sie angeblich das Attribut className in einem DOM-Element nicht finden kann. Ich bin etwas ratlos :slight_smile: . Ich habe gesehen, dass jemand loadScript verwendet, aber ich importiere die Bibliothek nur und die debounce-Funktion hat einfach funktioniert. Was ist der Unterschied zwischen den beiden Methoden?

Danke!

Hallo @hawm, ich habe herausgefunden, warum es nicht funktioniert und stecke fest.
Natürlich bin ich neu bei Ember und im Allgemeinen bei neuem JavaScript. Also habe ich ein wenig recherchiert und den Grund gefunden.
PgnViewerJs erwartet, mit dem echten DOM zu arbeiten, nicht mit dem virtuellen DOM. Selbst nachdem das erstellte Element übernommen wurde, ist es nicht im echten DOM vorhanden, und PGNV sucht nach IDs mithilfe von document.getElementById.
Ich habe alles studiert, was ich finden konnte: Ember-Komponenten scheinen meinen Bedürfnissen zu entsprechen, aber ich bin mir nicht sicher, wie ich damit umgehen soll.
Oder vielleicht API.onAppEvent?

Danke.

Ich habe later() von Ember verwendet und obwohl es ein schmutziger Hack ist, funktioniert es. Gibt es eine bessere Lösung?

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.