Caricare librerie JS tramite register_asset

Ho notato che i file JS aggiunti tramite register_asset nei plugin vengono passati come stringhe alla funzione eval.

Il problema con eval è che non aggiunge l’oggetto all’ambito globale, come discusso qui: https://stackoverflow.com/questions/4670805/javascript-eval-on-global-scope, il che è essenziale per utilizzare una libreria JavaScript.

Nello specifico, stavo cercando di usare https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC.js in un plugin, ma le funzioni non sono accessibili nei file di Ember.

La soluzione alternativa è elaborare il file con webpack, impostando libraryTarget su umd.

Molte librerie vengono elaborate in questo modo, il che sembra funzionare immediatamente.

Non sono un esperto in materia, ma mi chiedevo se abbia senso che Discourse aggiunga le risorse registrate all’ambito globale.

Nota: Scusate se tutto questo può sembrare banale. Non mi aspettavo di dover intervenire su webpack per far funzionare le librerie JS con Discourse, il che mi ha spinto a pubblicare questa spiegazione. :wink:

C’è qualcosa che non va qui: ho controllato il nostro plugin lazyYT che include una risorsa usando register_asset e non era all’interno di un blocco eval.

Potresti fornire un piccolo esempio di plugin che riproduce il problema?

Mi chiedo se questo sia un effetto collaterale non intenzionale di

(cioè, ciò avviene solo in ambiente di sviluppo)

Anch’io mi sono chiesto lo stesso: se è così, esistono delle soluzioni alternative, ma mi servirebbe un esempio riproducibile.

Certo.

Interessante. Posso eseguire il plugin in produzione per verificare se è questo il caso.

@eviltrout
Un piccolo plugin che utilizza la stessa libreria menzionata nell’OP GitHub - fzngagan/js-test · GitHub

Ho semplicemente provato a chiamare la funzione aggiunta dalla libreria nell’inizializzatore e nella console JS ottengo ReferenceError: RecordRTC is not defined

Ho utilizzato la versione non minificata della libreria, che potrebbe essere utile per il debug.

Inoltre, uno screenshot dalla scheda sources per mostrare che tutto è stato passato alla funzione eval.

Un’altra constatazione che ho fatto è che i file JS inclusi sia in discourse-spoiler-alert che in lazy-yt iniettano funzioni nell’oggetto jQuery globale, ma non dichiarano alcuna funzione a livello superiore.

Ho esaminato il tuo plugin e posso confermare che eval è presente solo in modalità di sviluppo. In produzione verrà inserito nell’ambito globale. Capisco che non sia l’ideale, ma penso anche che le librerie non dovrebbero essere distribuite senza un qualche tipo di supporto per i moduli (ad esempio, UMD).

Il mio suggerimento sarebbe di ricomporre il JS con un qualche supporto UMD e poi importarlo, ma la configurazione può essere piuttosto complessa se non si ha molta esperienza con i moduli JS.

In alternativa, un modo semplice per far funzionare tutto è modificare RecordRTC.js e aggiungere la riga seguente:

window.RecordRTC = RecordRTC;

Sarebbe ancora meglio racchiudere l’intero contenuto in un IIFE:

(function(exports) {
  // qui vanno i contenuti originali del file
  exports.RecordRTC = RecordRTC;
})(window);

Sì, sono d’accordo. Molte di esse vengono distribuite in questo modo e funzionano senza problemi. Grazie per aver indagato e per la conferma :+1: Ho optato per impacchettare la libreria tramite webpack e funziona anche senza importarla. Avrei dovuto testarla comunque in modalità produzione.