Как загрузить библиотеку в компонент темы

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

Привет, @merefield — всё ещё актуален ли этот способ?

Я пытаюсь подключить qrcode.js, чтобы генерировать QR-код в браузере.

Также возникает блокировка из-за 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 указаны верно), но браузер отказывается его загружать.

Результат выполнения loadscript — это промис, поэтому код, зависящий от него, нужно поместить в блок .then, как показано в моем примере.

Не знаю, связано ли это с чем-то подобным (я подозреваю, что нет), но черт возьми, это сводит меня с ума, потому что это должно быть просто сделать.

Большое спасибо!

Но я думал, что уже сделал это:

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

Я очень старался изменить ваш пример как можно меньше :slight_smile:

Возможно, мне нужно использовать .then, когда я пытаюсь использовать код позже?

Но это не решает проблему CSP, верно?

image

Мои два главных совета:

Разместите библиотеку в папке assets

Это решает проблему CSP, делает тему самодостаточной и считается хорошей практикой, в отличие от загрузки из сторонних источников.

Загружайте её лениво

Только при необходимости вы можете загрузить её лениво, используя await loadScript. Это означает, что она не будет загружаться на страницах, где не нужна, замедляя весь ваш сайт.


Хорошим примером темы, которая следует этим лучшим практикам, является GitHub - discourse/discourse-mermaid-theme-component · GitHub

Да, именно так. :+1:. В моём примере всё работает именно так.

Ещё один вопрос: в чём разница между ...initializers/mycode.js и ...api-initializers/mycode.js?

И огромное спасибо вам обоим!!

Это был отличный пример! Мне удалось во всём разобраться!

Что ж, я думал, что следовал вашему примеру. JavaScript всё ещё кажется запутанным лабиринтом, где все проходы выглядят одинаково.