I noticed that the js files added using register_asset via plugins are passed as a string to eval function.
The problem with eval is, it doesn’t add the object to the global scope as discussed here. https://stackoverflow.com/questions/4670805/javascript-eval-on-global-scope which is essential for using a js library.
To be specific, I was trying to use https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC.js in a plugin but the functions aren’t accessible in the ember files.
The workaround for this is to process the file with webpack, using libraryTarget as umd.
Many of the libraries are processed this way which seems to work out of the box.
Now I’m not an expert on these things, but just wondering whether it makes sense for discourse to add the registered assets to the global scope.
Note: Apologies if some of this sounds silly. I didn’t expect to fiddle with webpack to get js libraries working with discourse which motivated me to post this writeup.
Another finding I have is that the included js files in both the discourse-spoiler-alert, and lazy-yt inject functions into the global jQuery object but do not declare any top level functions.
I looked at your plugin and I can confirm the eval is only present in development mode. In production it will be inserted in the global scope. I understand that’s not ideal but I also don’t think libraries should normally be distributed without some kind of support for modules (for example, UMD.)
My suggestion would be to repackage the JS with some kind of UMD support and then import it but that is somewhat tricky to set up if you don’t have a lot of JS experience with modules.
Instead, an easy way to get this to work is to edit RecordRTC.js and add the following line:
window.RecordRTC = RecordRTC;
It would be even better to surround the entire contents in an IIFE:
(function(exports) {
// original file contents go here
exports.RecordRTC = RecordRTC;
})(window);
Yes, I agree. Many of them are distributed that way and those work seamlessly. Thanks for looking into this and for the confirmation I went the route of packaging the library via webpack and it works without even importing. I should have tested in production mode though.