Cargar librerías JS mediante register_asset

He notado que los archivos JS agregados mediante register_asset a través de plugins se pasan como una cadena a la función eval.

El problema con eval es que no agrega el objeto al ámbito global, como se discute aquí: https://stackoverflow.com/questions/4670805/javascript-eval-on-global-scope, lo cual es esencial para usar una biblioteca de JS.

Para ser específico, intentaba usar https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC.js en un plugin, pero las funciones no son accesibles en los archivos de Ember.

La solución temporal es procesar el archivo con webpack, utilizando libraryTarget como umd.

Muchas bibliotecas se procesan de esta manera, lo que parece funcionar sin problemas.

Ahora, no soy un experto en estos temas, pero me pregunto si tiene sentido que Discourse agregue los activos registrados al ámbito global.

Nota: Disculpas si algo de esto suena tonto. No esperaba tener que manipular webpack para que las bibliotecas de JS funcionen con Discourse, lo que me motivó a publicar esta reflexión. :wink:

Algo parece estar mal aquí: revisé nuestro plugin lazyYT que incluye un activo usando register_asset y no estaba dentro de un bloque eval.

¿Podrías proporcionar un ejemplo pequeño de un plugin que reproduzca el problema?

Me pregunto si esto es un efecto secundario no deseado de

(es decir, esto solo ocurre en desarrollo)

Yo también me pregunté eso: si ese es el caso, existen soluciones alternativas, pero me gustaría un ejemplo reproducible.

Claro.

Interesante. Puedo ejecutar el plugin en producción para verificar si ese es el caso.

@eviltrout
Un pequeño plugin que utiliza la misma biblioteca mencionada en el OP GitHub - fzngagan/js-test · GitHub

Simplemente intenté llamar a la función agregada por la biblioteca en el inicializador y en la consola de JS obtengo ReferenceError: RecordRTC is not defined.

He utilizado la versión sin minificar de la biblioteca, lo cual podría ser útil para la depuración.

Además, una captura de pantalla de la pestaña sources para mostrar que todo se pasó a la función eval.

Otro hallazgo que tengo es que los archivos JS incluidos en ambos discourse-spoiler-alert y lazy-yt inyectan funciones en el objeto jQuery global, pero no declaran ninguna función de nivel superior.

He revisado tu plugin y puedo confirmar que eval solo está presente en modo de desarrollo. En producción, se insertará en el ámbito global. Entiendo que no es lo ideal, pero tampoco creo que las bibliotecas deban distribuirse normalmente sin algún tipo de soporte para módulos (por ejemplo, UMD).

Mi sugerencia sería volver a empaquetar el JS con algún tipo de soporte UMD y luego importarlo, pero eso puede ser un poco complicado de configurar si no tienes mucha experiencia con módulos de JS.

En su lugar, una forma sencilla de hacer que esto funcione es editar RecordRTC.js y agregar la siguiente línea:

window.RecordRTC = RecordRTC;

Sería aún mejor envolver todo el contenido en un IIFE:

(function(exports) {
  // el contenido original del archivo va aquí
  exports.RecordRTC = RecordRTC;
})(window);

Sí, estoy de acuerdo. Muchas de ellas se distribuyen de esa manera y funcionan perfectamente. Gracias por investigar esto y por la confirmación :+1: Opté por empaquetar la biblioteca mediante webpack y funciona sin necesidad de importarla. Sin embargo, debería haberlo probado en modo de producción.