主题组件中的 Javascript 资源

我正在尝试构建一个 STL 预览主题组件。有一个优秀的 JavaScript 库可以实现此功能,但我不确定如何在主题组件中使用它。

它是普通的 JavaScript,而不是 ES6,我认为这意味着我不能直接把它放在“javascripts”目录中并导入它,对吗?此外,该库似乎依赖于通过 <script> 标签导入。

所以我可以创建一个 <script> 标签并将其添加到文档的 <head> 中,但我该如何找到该库 JS 文件的名称呢?另外,该库由多个 JS 文件组成,它假设这些文件位于同一目录中。它还会创建额外的 <script> 标签来加载库的其余部分。

那么,这些文件应该放在“javascripts”目录中吗?还是应该将它们视为资源(assets)?我能找到的最接近的类似做法是 discourse-math 插件,但如果可能的话,我更希望将其保持为主题组件。

这似乎展示了如何为插件操作:How to ship javascript library with plugin?
我仍然没有找到关于主题组件的任何相关内容。

我不知道,但你也没有给出什么好答案!

接下来要关注的是……那个……在主题组件中包含其他文件的问题。

我认为可以看看一些大型的主题组件。基本上,主题组件的文件结构是相同的,Ember 会像加载插件一样加载这些主题文件。

我不这么认为,每个组件应该都有自己的虚拟目录,比如 discourse/theme-10/…… 所以要从那里加载内容,我至少得知道目录是什么。

1 个赞

资源名称似乎只能通过变量访问,而实际名称是冗长复杂的数字,因此这行不通。
看起来目前无法将其作为组件实现,所以我打算暂时通过 Nginx 侧载 JS 文件并以此方式访问它们。不幸的是,这可能意味着该组件仅对我有效。

您可以在主题组件内的 header.html 文件中添加标准的 script 标签。

侧载可以工作!
但只有一次。:frowning:

如果我导航到另一个主题,然后再返回到包含 STL 的主题,它就不工作了。我不确定原因,因为 JavaScript 控制台中没有报错。我之前看到过一个帖子,讨论了 onload 的奇怪现象,既然这些脚本使用了 onload,也许与此有关?

没错,但 viewstl 代码不适合内联。
通过侧载,我在 common/head_tag.html 中添加了如下 script 标签:

<script src="/xi/viewstl/stl_viewer.min.js"></script>

(/xi/ 由 nginx 提供服务)

Discourse 是一个单页应用(SPA)。你不能简单地添加一个 onLoad 脚本,因为那样无法生效。你需要接入我们的 API 端点。请查看 Discourse 主题开发者指南

好的,那我这就尝试用其他方式替换掉那些老旧的基于 script 标签的加载方式。

我已经把这一页读了好几遍,但还是无法让它正常工作。
我正尝试通过 import 语句加载 three.js,但无论我怎么做,系统都抱怨找不到该导入。奇怪的是,我可以正常导入其他文件,而且错误信息完全没帮助。

不管怎样,以下是我遇到的情况,或许有人能帮忙:

这是无法工作的导入语句:

以下是我收到的错误:

_application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:74333 "STL 预览”主题/组件中发生错误:Error: 找不到从 `discourse/theme-17/stlviewer/StlViewer` 导入的模块 `discourse/theme-17/three/build/three.module`
    at h (_ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74612)
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74581
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74665
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74490
    at require (_ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74663)
    at h (_ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74616)
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74581
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74665
    at _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74490
    at require (_ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:74663)
(anonymous) @ _application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:74333
u @ _application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:74325
initialize @ _application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:74304
i.initialize @ _application-547e0be66174ffd22a4d74fd8b568f6a3892a266cff18cb078c08d6357227acb.js:7723
(anonymous) @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:49335
e.each @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67724
e.walk @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67638
e.each @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67568
e.topsort @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67576
_runInitializer @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:49361
runInitializers @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:49333
_bootSync @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:47768
domReady @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:47668
n._run @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67275
n._join @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:67251
n.join @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:66968
f @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:53760
(anonymous) @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:53864
l @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3776
c @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3844
setTimeout (async)
(anonymous) @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3882
u @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3510
fireWith @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3640
fire @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3648
u @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3510
fireWith @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:3640
ready @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:4120
z @ _ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.js:4130

“.”是某种神奇的模块分隔符吗?

我猜“.”是特殊的,因为当我把 three.module.js 重命名为 three_module.js 时,会出现一个完全不同的问题:我无法再加载主题了(500 错误)。

我也尝试过直接从 CDN 导入 three.js 并使用完整 URL,但这似乎也不行……

如果你只需要按需加载 JavaScript 资源(就像我这里需要加载 D3 库一样),可以结合 Loadscript 使用以下模式:

以及更靠上的部分:

Loadscript 会返回一个 Promise,因此你需要对结果调用 .then。(我不完全确定,但推测结果会被隐式缓存,因此第二次执行时会更快等。)

正如你所见,你可以将它们串联起来,依次加载多个脚本。

请注意,这段代码运行在 Ember 组件内部,并在 didInsertElement 钩子中触发。有关 Ember 组件的更多信息,请访问:Templates are HTML - Components - Ember Guides

另外请注意,脚本本身存放在 javascripts/assets 目录中。

我的实现参考了 @j.jaffeux 在某处用于加载完全不同脚本的代码(感谢 Joffrey!:+1:

下面是一个 Discourse 示例:

提示:务必查阅官方和 Pavilion 主题社区(TCs)以及插件中实现类似功能的内容,看看它们是如何做到的 :)。

4 个赞

有意思,谢谢指点。
我会尝试使用 loadScript,看看能否解决我的问题。

2 个赞

我决定尝试一种更简单的方法。
我只创建一个 iframe,加载一个 HTML 页面,该页面可以执行所有复杂的脚本操作以使预览正常工作。目前它还不是可复用的格式,但为其创建一个插件相对简单。