Problemi nel caricare un asset js da un Theme Component

Ciao, è la prima volta che sviluppo su Discourse, quindi scusa per le domande sciocche.
Sto creando un componente tema per visualizzare PGN (scacchiere e partite).
Il componente non è teoricamente difficile, c’è un componente js per questo (PGNViewer.js) e sono riuscito a tradurre i tag [wrap] nei blocchi \u003cscript\u003evar x='pgn here'; ...\u003c/script\u003e e \u003cdiv class='pgn-blahblah'\u003e\u003c/div\u003e appropriati.
Fin qui tutto bene, ma ora devo caricare il js.
Ho scoperto che posso usare import loadScript from \"discourse/lib/load-script\"; e await loadScript(settings.theme_uploads_local.pgnviewer_js); per caricarlo al momento dell’inizializzazione dalla directory /assets/.
Ma ho alcuni problemi qui.
Nonostante riesca a caricare il componente nell’installazione di sviluppo, non ci riesco sul mio server di produzione, perché dice che l’asset è troppo grande. C’è un modo per risolvere questo problema?
In secondo luogo, nell’installazione di sviluppo, vedo un avviso che indica che non è stato possibile caricare /theme-javascripts/dist.js.map. Non ho idea da dove provenga. C’è qualcosa che dovrei fornire?
Nel complesso, questo approccio è corretto o sarebbe meglio implementare un plugin?
Grazie
Cordiali saluti

FF

2 Mi Piace

Benvenuto in Meta, @happycactus :wave:

Sì, probabilmente. L’unica ragione per cui avresti bisogno di un plugin è se stessi cercando di cambiare l’API (cioè il backend).

Ho avuto un problema simile in passato.

Sì, devi cambiare app.yml per consentire ai file di grandi dimensioni di essere gestiti tramite il proxy inverso (nginx).

Fortunatamente questa è un’impostazione semplice, upload_size:, qui nel contesto:

params:
  ## Quale revisione Git dovrebbe usare questo container? (default: tests-passed)
  version: tests-passed

  ## Dimensione massima di upload (default: 10m)
  upload_size: 20m

Una volta modificato, dovrai ricostruire affinché abbia effetto:

./launcher rebuild app

Naturalmente, questo presuppone che tu abbia un accesso appropriato al server…

2 Mi Piace

Grazie, Robert!

Sono nel dubbio, probabilmente perché ho zero esperienza con tali piattaforme.
Il mio dubbio è:

il mio approccio è quello di “incorporare” il piccolo snippet di javascript necessario per riempire il blocco div con il contenuto, ma vedo che forse potrei eseguirlo da una funzione “cookPgn”, come viene fatto nel componente mermaid:

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);
  });

In questo modo, se ho capito bene, non ho bisogno di caricare lo script dalla pagina (usando loadScript forse??) ma posso semplicemente importarlo nel js del tema? O probabilmente sono completamente fuori strada!
Voglio dire, qual è la differenza tra loadScript e un semplice import?
Puoi indirizzarmi a qualche risorsa web dove posso capire meglio questo?
Scusa ancora se le domande sono banali o stupide!

Un’altra cosa, il limite è di default a 10M, ma il mio asset è di circa 300kb, e l’intero zip è 337kb, ancora durante il caricamento dice che è più di 512kb.

Grazie,

FF

Hai provato un import? Non credo che tu possa importare uno script esterno.

Loadscript è l’approccio giusto e garantisce che lo script sia completamente caricato prima che il tuo codice proceda e lo utilizzi (questo è il motivo per cui restituisce una promise).

puoi condividere l’errore esatto - è nella console del browser?

Il tuo vero problema è che stai cercando di usare JS inline, cosa proibita da CSP.

Metti questo codice in una funzione helper nel codice del tuo componente del tema e non iniettarlo all’interno dei post.

Carica il tuo tema corrente su GitHub e possiamo dargli un’occhiata.

5 Mi Piace

Dai un’occhiata al componente Discourse Mermaid, che carica una libreria e fa succedere cose ai post.

2 Mi Piace

Grazie, @Falco, questo era uno dei miei dubbi.

Certo, eccolo: GitHub - studiofuga/discourse-pgn-component: A theme component for Discourse to display PGN blocks
Esiste anche una versione plugin, ma penso che non seguirò questo approccio e rimarrò sul componente tema.

Grazie @pfaffman, in effetti mi sono ispirato ad esso, e ho notato che fa esattamente ciò di cui ho bisogno e nel modo corretto, senza iniettare il codice come suggerito sopra.

Grazie a tutti, proverò con i vostri suggerimenti e tornerò con i risultati. Naturalmente il mio codice è open source, quindi ogni contributo o critica è molto benvenuta.

1 Mi Piace

Colpa mia, ho dimenticato di aver limitato la dimensione dell’allegato a 512kB, l’ho aumentata al valore predefinito (4096) e ha funzionato bene. Grazie e scusa per la stupida domanda.

2 Mi Piace

Ok, ho risolto tutto e il componente funziona! Ma abbiamo un problema, una “unsafe eval” nella libreria che sto usando. Immagino che dovrei correggere la libreria upstream, non ho idea di come impacchettarla.
Per chi fosse interessato, ho caricato tutte le mie modifiche nel mio repository sopra, ed ecco i dettagli dell’errore.

e la riga è questa (nel modulo js originale)

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

qui.

1 Mi Piace

Il tuo script sta avendo problemi con la Content Security Policy in produzione.

Devi aggiungere 'unsafe-eval' come voce nell’impostazione del sito: content security policy script src

Grazie, sto consultando la documentazione per vedere come fare. :slight_smile: Sto imparando molto, grazie

1 Mi Piace

Ok, l’ho fatto, solo che ho dovuto usare il ’ … lol… Comunque, il mio script ha quasi funzionato, ho caricato tutto su main e in qualche modo ha funzionato, sembra che abbia un problema con il rendering ma almeno il componente principale viene chiamato (sospetto che sia lì il problema).
Grazie a tutti… Tornerò presto con altre domande LOL. Grazie!

1 Mi Piace

Tenendo presente che l’aggiunta di unsafe-eval alla tua CSP rimuove fondamentalmente lo scopo della CSP e rende il tuo sito meno sicuro di conseguenza.

L’uso di eval è un code smell e dovrebbe essere corretto a monte come hai indicato sopra.

4 Mi Piace

Sì, assolutamente. Al momento non riesco a risolvere il problema, ma il mio piano è di correggere prima il mio componente, poi la libreria upstream e rimuovere l’override della CSP.
Grazie per il consiglio!

Ho quasi finito. Sono riuscito a visualizzare “qualcosa” ma funziona in modo casuale.
La libreria JS che sto usando funziona in questo modo:

Per prima cosa dobbiamo definire un blocco <div id='board'> con un ID univoco. poi dobbiamo lanciare una funzione per popolare il div, qualcosa del genere. PGNV.pgnBoard('board', {});. Lo script richiede lo stesso ID per popolarlo.

Se ho capito bene, non posso farlo mentre decoro il blocco cotto, perché il documento non è ancora popolato e l’oggetto PGNV non è in grado di trovare il blocco. Quindi ho usato prima un widget (non funziona, perché la funzione HTML deve restituire il blocco e io non ce l’ho), poi sono passato a una funzione debounced: debounceFunction(this, renderPgn, attrs, 200);.

Ma funziona “a volte”.

Cosa mi sto perdendo?

Grazie

debounceFunction ritarda la chiamata al metodo di destinazione finché il periodo di debounce non è trascorso senza ulteriori chiamate di debounce, a volte potrebbe non funzionare ancora perché

debounce potrebbe non essere la soluzione nel tuo caso d’uso

Prova a usare le opzioni afterAdopt

1 Mi Piace

Ciao Hawn, grazie per il tuo suggerimento!
Sembra esattamente quello che stavo cercando. Ho provato due approcci diversi:

  • prima usare il normale “decorateCooked” per analizzare e allegare il blocco div e poi afterAdopt per renderizzare chiamando PGNV.pgnviewer() o
  • usare solo l’opzione afterAdopt per allegare e renderizzare
    nessuno ha funzionato per un altro problema che non riesco a comprendere appieno, sembra che la libreria interna vada in crash con un errore, non riuscendo a trovare l’attributo className apparentemente in un elemento DOM. Sono un po’ perso :slight_smile: . Ho visto che qualcuno usa loadScript, ma io ho semplicemente importato la libreria e la funzione debounce ha funzionato. Qual è la differenza tra i due metodi?

Grazie!

Ciao @hawm, ho scoperto perché non funziona e sono bloccato.
Naturalmente sono completamente nuovo a Ember e al JS recente in generale. Quindi ho studiato un po’ e ho scoperto il motivo.
PgnViewerJs si aspetta di funzionare sul DOM reale, non sul Virtual DOM. Quindi, anche dopo che l’elemento “cotto” è stato adottato, non è presente nel DOM reale e PGNV cerca gli ID usando document.getElementById.
Ho studiato tutto quello che ho potuto trovare: i componenti Ember sembrano adatti alle mie esigenze, ma non sono sicuro di come gestirli.
O forse API.onAppEvent?

Grazie.

Ho usato later() di ember e, sebbene sia una soluzione “sporco”, funziona.
C’è una soluzione migliore?

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