通过 register_asset 加载 js 库

我注意到,通过插件使用 register_asset 添加的 js 文件会以字符串形式传递给 eval 函数。

eval 的问题在于,正如在 https://stackoverflow.com/questions/4670805/javascript-eval-on-global-scope 中讨论的那样,它不会将对象添加到全局作用域,而这对使用 js 库至关重要。

具体来说,我尝试在插件中使用 https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC.js,但其函数在 ember 文件中无法访问。

一个变通方法是通过 webpack 处理该文件,并将 libraryTarget 设置为 umd

许多库都经过这样的处理,看起来可以开箱即用。

我并非这方面的专家,但只是想知道,Discourse 是否应该将已注册的资产添加到全局作用域中。

注:如果以上内容听起来有些愚蠢,敬请见谅。我没想到需要折腾 webpack 才能让 js 库在 Discourse 中正常工作,这也促使我写了这篇帖子。:wink:

1 个赞

这里似乎有些不对劲——我查看了我们的 lazyYT 插件,它使用 register_asset 包含了一个资源,但并没有放在 eval 块中。

能否提供一个能复现该问题的小型插件示例?

2 个赞

我在想这是否是

的一个非预期的副作用(即,这种情况仅发生在开发环境中)

1 个赞

我也这么想过——如果是这种情况,确实有变通方法,但我还是想要一个可复现的示例。

2 个赞

当然可以。

有意思。我可以在生产环境中运行该插件,以确认是否确实如此。

@eviltrout
一个使用 OP 中提到的同一库的小型插件:GitHub - fzngagan/js-test · GitHub

我只是尝试在初始化器中调用该库添加的函数,但在 JS 控制台中我收到 ReferenceError: RecordRTC is not defined 错误。

我使用了该库的未压缩版本,这可能有助于调试。

另外,附上一张来自“源代码”标签页的截图,以显示整个内容都被传递给了 eval 函数。

我另一个发现是,discourse-spoiler-alertlazy-yt 中包含的 JS 文件都会向全局 jQuery 对象注入函数,但并未声明任何顶层函数。

我查看了您的插件,可以确认 eval 仅存在于开发模式中。在生产环境中,它将被插入到全局作用域。我明白这并不理想,但我也不认为库通常应该在没有任何模块支持(例如 UMD)的情况下发布。

我的建议是使用某种 UMD 支持重新打包 JS,然后通过 import 引入它,但如果您没有太多关于模块的 JS 经验,设置起来会有些棘手。

另一种简单的解决方法是编辑 RecordRTC.js 并添加以下代码行:

window.RecordRTC = RecordRTC;

更好的做法是将整个文件内容包裹在一个 IIFE 中:

(function(exports) {
  // 原始文件内容放在这里
  exports.RecordRTC = RecordRTC;
})(window);
5 个赞

是的,我同意。许多库就是这样分发的,它们可以无缝工作。感谢你调查此事并确认 :+1: 我采用了通过 webpack 打包库的方式,甚至无需导入即可正常工作。不过,我本应该在生产模式下进行测试的。

1 个赞