如何在主题组件中加载库

from How to require external libraries in a component helper file? - #2 by merefield

@merefield – 这是仍然是这样做的方法吗?

我正在尝试引入 qrcode.js 来在浏览器中生成 QRcode。

我被 CSP 阻止了,我不明白为什么这是 CSP 问题,因为它在同一个主机上。这在生产服务器上使用 discourse_theme 进行调试。

我正在将其放入一个初始化程序:

import loadScript from "discourse/lib/load-script";
import { withPluginApi } from "discourse/lib/plugin-api";
// import QRCode from "discourse/lib/qrcode";
export default {
  name: "qrcode",
  ensureQRCode() {
    window.console.log(settings.theme_uploads.QRCode);
    return loadScript(settings.theme_uploads.QRCode).then(() => {
      return loadScript(settings.theme_uploads.QRCode);
    });
  },
  initialize(container) {
    withPluginApi("0.8.7", (api) => {
      api.decorateCookedElement((cooked, postWidget) => {
        const placeholderNodes = cooked.querySelectorAll(
          ".d-wrap[data-wrap=qrcode]"
        );
        this.ensureQRCode();
        // const qr = new QRCode(
        //   document.getElementById("qrcode"),
        //   "http://jindo.dev.naver.com/collie"
        // );
...

而且,如果我不调用 this.ensureQRCode();,该函数似乎不会被调用来加载脚本,而你在你的组件中似乎没有这样做。

脚本是可用的,并且我可以检索它(所以我正确地获取了 about.json/assets/qrcode.js 中的内容),但浏览器拒绝加载它。

2 个赞

您的 loadscript 的结果是一个 promise,因此您需要按照我的示例代码,将依赖于它的代码放在 .then 块中。

3 个赞

我不知道这是否是类似的事情(我怀疑不是),但这真的让我很抓狂,因为这本该很简单。

1 个赞

非常感谢!

但我以为我已经这样做了:

    return loadScript(settings.theme_uploads.QRCode).then(() => {
      return loadScript(settings.theme_uploads.QRCode);
    });

我尽量少改你的例子 :slight_smile:

也许我以后使用代码时需要使用.then

但这并不能解决CSP问题,对吧?

image

2 个赞

我的两个主要建议是:

将库放在 assets 文件夹中

这可以解决 CSP 问题,使主题自包含,并且被认为是良好的实践,而不是从第三方加载。

延迟加载

仅在需要时,您可以使用 await loadScript 延迟加载它。这意味着它不会在不需要它的页面上加载,从而减慢整个网站的速度。


一个遵循这些良好实践的主题示例是 GitHub - discourse/discourse-mermaid-theme-component

6 个赞

是的,正是这样。:+1:。这正是我示例中的工作方式。

3 个赞

还有一个问题:...initializers/mycode.js...api-initializers/mycode.js 有什么区别?

非常感谢你们两位!!

确实是个好例子!我能理解了!

嗯,我以为我遵循了你的例子。JavaScript 仍然像一个曲折的通道迷宫,看起来都差不多。

3 个赞