# How to load library in a theme component

**URL:** https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621
**Category:** Development
**Created:** [August 25, 2023, 2:54pm UTC](https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621 "2023-08-25T14:54:17Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [August 25, 2023, 2:54pm UTC](https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621/1 "2023-08-25T14:54:17Z")

</div>

from [How to require external libraries in a component helper file? - #2 by merefield](https://meta.discourse.org/t/how-to-require-external-libraries-in-a-component-helper-file/195392/2)

> [@How to require external libraries in a component helper file?](https://meta.discourse.org/t/how-to-require-external-libraries-in-a-component-helper-file/195392/2):
>
> You can use the approach I use in [GitHub - merefield/discourse-tc-tag-cloud: A Discourse Theme Component that displays a tag cloud above the tag lists on the tags page](https://github.com/merefield/discourse-tc-tag-cloud)

Hey @merefield – Is this still how to do this?

I’m trying to pul in [qrcode.js](https://davidshimjs.github.io/qrcodejs/) to generate a QRcode in the browser.

I’m getting blocked by CSP as well. I don’t understand how it’s a CSP problem if it’s on the same host. This is on a production server using `discourse_theme` to debug.

I’m putting this in an initializer:

```plaintext
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"
        // );
...

```

And it seems that the function doesn’t get called to load the script if I don’t call ` this.ensureQRCode();`, which you don’t seem to be doing in your component.

The script is available and I can retrive it (so I got the stuff in the `about.json` and `/assets/qrcode.js` right), but the browser refuses to load it.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 25, 2023, 2:56pm UTC](https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621/2 "2023-08-25T14:56:10Z")

</div>

The result of your loadscript is a promise so you need to put your code relying on it in a `.then` block as per my example code

---

<div class="post-metadata">

### Author: ![Lilly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lilly/32/575047_2.png) [@Lilly](https://meta.discourse.org/u/Lilly)
#### Post date: [August 25, 2023, 3:04pm UTC](https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621/3 "2023-08-25T15:04:10Z")

</div>

I don’t know if this is a similar thing (I suspect it isn’t) but holy smoly is it driving me nuts because this should be simple to do.

> <https://github.com/Lillinator/redirect-to-profile/blob/main/javascripts/discourse/components/user-card-contents.js.es6>

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [August 25, 2023, 3:05pm UTC](https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621/4 "2023-08-25T15:05:54Z")

</div>

Thanks very much!

But I thought I did that:

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

```

I tried very hard to change your example as little as possible 🙂

Maybe I need to use a `.then` when I’m trying to use the code later?

But that doesn’t solve the CSP issue, does it?

![image](https://global.discourse-cdn.com/meta/original/4X/4/a/d/4adee628014aeef20a6560f2e696bf147104715e.png)

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [August 25, 2023, 3:17pm UTC](https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621/5 "2023-08-25T15:17:39Z")

</div>

My two main advices are:

### Put the library in the assets folder

This solves CSP, makes the theme self-contained and is considered a good practice, instead of loading it from third-parties.

### Load it lazily

Only when needed, you can load it lazily using `await loadScript`. This means it won’t be loaded in pages where it isn’t needed, slowing your whole site.

* * *

A good example of a theme that follows those good practices is [GitHub - discourse/discourse-mermaid-theme-component · GitHub](https://github.com/discourse/discourse-mermaid-theme-component)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 25, 2023, 6:30pm UTC](https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621/6 "2023-08-25T18:30:01Z")

</div>

> [@pfaffman](#):
>
> Maybe I need to use a `.then` when I’m trying to use the code later?

Yes, precisely. 👍. That’s how it works in my example.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [August 25, 2023, 9:20pm UTC](https://meta.discourse.org/t/how-to-load-library-in-a-theme-component/276621/7 "2023-08-25T21:20:50Z")

</div>

One more question: What’s the difference between `...initializers/mycode.js` and `...api-initializers/mycode.js`?

### And much thanks to both of you!!

> [@Falco](#):
>
> A good example of a theme that follows those good practices is [GitHub - discourse/discourse-mermaid-theme-component](https://github.com/discourse/discourse-mermaid-theme-component)

That **was** a good example! I was able to make sense of it!

> [@merefield](#):
>
> Yes, precisely. 👍. That’s how it works in my example.

Well, I thought I followed your example. Javascript still seems like a twisty maze of passages that all look alike.
