# Include JS in a html custom module

**URL:** <https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434>\
**Category:** General\
**Created:** [22 April 2019 18:13 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434 "2019-04-22T18:13:47Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![linhtranvu](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/linhtranvu/32/30053_2.png) [@linhtranvu](https://discourse.nodered.org/u/linhtranvu)\
**Post date:** [22 April 2019 18:13 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/1 "2019-04-22T18:13:47Z")

</div>

I am writing my very first module and want to do the most basic thing, include a js in HTML or JS file of module. This is what I want to do

**my-node.html**

```auto
<script type="text/javascript">
    RED.nodes.registerType('create-issue', {
        .
        .
        .
        oneditprepare: function() {
            // some kind of require here
            myVeryLargeFunction();
        }
        .
        .
        .
    });
</script>

```

**my-very-large-function.js**

```auto
function myVeryLargeFunction() {
    // Do stuff here
}

```

So could anyone help me, tks

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [22 April 2019 19:09 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/2 "2019-04-22T19:09:44Z")

</div>

Use import or require in your js file as you would any other project.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [22 April 2019 19:23 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/3 "2019-04-22T19:23:33Z")

</div>

example...

```auto
const fs = require('fs');

module.exports = function(RED) {
    "use strict";
    //use fs
}

```

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [22 April 2019 19:55 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/4 "2019-04-22T19:55:18Z")

</div>

For an example see the getscript part of the geofence html file. [https://github.com/hardillb/node-red-node-geofence/blob/master/geofence.html](https://github.com/hardillb/node-red-node-geofence/blob/master/geofence.html)

Steve, this is browser side. You can’t just require as you would in node

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [22 April 2019 20:24 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/5 "2019-04-22T20:24:51Z")

</div>

Yes of course I missed that.

---

<div class="post-metadata">

**Author:** ![linhtranvu](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/linhtranvu/32/30053_2.png) [@linhtranvu](https://discourse.nodered.org/u/linhtranvu)\
**Post date:** [23 April 2019 03:23 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/6 "2019-04-23T03:23:15Z")

</div>

I got getScript function, tks alot. I will test now

---

<div class="post-metadata">

**Author:** ![Holger-Will](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/holger-will/32/7302_2.png) [@Holger-Will](https://discourse.nodered.org/u/Holger-Will)\
**Post date:** [28 April 2019 03:07 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/7 "2019-04-28T03:07:00Z")

</div>

i was working on this for last few days as well... the most important part is not the `getScript` function, but rather making the static folder available with:

```auto
RED.httpAdmin.get('/enocean-js/*', function(req, res){
        var options = {
            root: __dirname + '/static/',
            dotfiles: 'deny'
        };
        res.sendFile(req.params[0], options);
    });

```

in your nodes `.js` file

with that in place, you can just include your external scrips like you would normally do in your nodes `.html` file:

`<scritp src="enocean-js/my-very-large-function.js"></script>`

looking at the `geofence` repo lead me to the right path, though...

---

<div class="post-metadata">

**Author:** ![Holger-Will](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/holger-will/32/7302_2.png) [@Holger-Will](https://discourse.nodered.org/u/Holger-Will)\
**Post date:** [28 April 2019 11:37 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/8 "2019-04-28T11:37:07Z")

</div>

as advised on github i will add my request here...

while i was working on this, i realized that you can not load  
`<script type="module"></script>`

currently i overcome this by injecting the script tag myself with

```auto
var st = document.createElement("script")
st.setAttribute("type","module")
st.setAttribute("src","enocean-js/test.js")
document.body.appendChild(st)

```

that seems a bit hackish to me, so i would really like to get this working cleanly.

I would like to write a PR for getting this to work. But as i'm still quite new to node-red it would be great if someone can give me a pointer in the right direction where loading the nodes `.html` file happens in the core.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [28 April 2019 11:56 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/9 "2019-04-28T11:56:45Z")

</div>

not sure why that wouldn't work ? you haven't added the src in the \<script version but I assume that is just a bad cut/paste ? What errors do you get ? Main thing is as you point out previously to ensure the server endpoint is in place.

\<edit\>oh yeah - on the client side we already have specific bits of script tags we look for so you can't have script inside script. Is that the problem ? where are you injecting your tag ? in oneditprepare ?

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [28 April 2019 13:25 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/10 "2019-04-28T13:25:42Z")

</div>

You don't need script inside script. The core debug node uses a script tag to load another file: [https://github.com/node-red/node-red/blob/c7587960fbfe77a1609e7c3c29705bc1d5918dc3/packages/node\_modules/%40node-red/nodes/core/core/58-debug.html#L34](https://github.com/node-red/node-red/blob/c7587960fbfe77a1609e7c3c29705bc1d5918dc3/packages/node_modules/%40node-red/nodes/core/core/58-debug.html#L34)

@Holger-Will I'm not clear what you are asking for here that you cannot already do?

---

<div class="post-metadata">

**Author:** ![Holger-Will](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/holger-will/32/7302_2.png) [@Holger-Will](https://discourse.nodered.org/u/Holger-Will)\
**Post date:** [28 April 2019 14:17 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/11 "2019-04-28T14:17:50Z")

</div>

What i'm trying to do is using esm modules

### Test 1

```auto
<script type="text/javascript">
    RED.nodes.registerType(...bla bla bla)
    console.log("one")
</script>
<script type="text/javascript">
    console.log("two")
</script>

```

logs: "one" and "two"

### Test 2

```auto
<script type="text/javascript">
    RED.nodes.registerType(...bla bla bla)
    console.log("one")
</script>
<script type="module">
    console.log("two")
</script>

```

this only logs "one"

### Test 3

using an external file ("enocean-js/test.js")

```auto
import { foo } from 'bar'
console.log("three")

```

```auto
<script type="text/javascript">
    RED.nodes.registerType(...bla bla bla)
    console.log("one")
</script>
<script type="module" src="enocean-js/test.js"></script>

```

i get: `Uncaught SyntaxError: Unexpected token {`  
that's the same error you get when you try to use esm modules without `type="module"`

### Test 4

agian using the external file ("enocean-js/test.js")

```auto
import { foo } from 'bar'
console.log("three")

```

```auto
<script type="text/javascript">
    RED.nodes.registerType(...bla bla bla)
    console.log("one")
    var st = document.createElement("script")
    st.setAttribute("type","module")
    st.setAttribute("src","enocean-js/test.js")
    document.body.appendChild(st)
</script>

```

logs "one" and "three", and esm modules work as expected, no error

### conclusion

from these test it seems that the attribute `type="module"` gets lost somewhere during registration

---

<div class="post-metadata">

**Author:** ![Holger-Will](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/holger-will/32/7302_2.png) [@Holger-Will](https://discourse.nodered.org/u/Holger-Will)\
**Post date:** [28 April 2019 19:30 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/12 "2019-04-28T19:30:14Z")

</div>

obsolete... see next reply

---

<div class="post-metadata">

**Author:** ![Holger-Will](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/holger-will/32/7302_2.png) [@Holger-Will](https://discourse.nodered.org/u/Holger-Will)\
**Post date:** [28 April 2019 20:45 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/13 "2019-04-28T20:45:25Z")

</div>

for **Test 3** i have a fix in my local branch now... it's pretty easy:  
after line 45 in `packages/node_modules/@node-red/editor-client/src/js/red.js`

```auto
if( $(el).attr('type') === "module"){
  newScript.type = "module"
}

```

i could create a PR if you like.

> <https://github.com/Holger-Will/node-red/blob/ed07393a3346a388d04c2b55431c038b469dc6c1/packages/node_modules/%40node-red/editor-client/src/js/red.js#L46>

### Edit

**Test 2** is caused by a bug in jQuerys `append` function. it's fixed in jQuery 3.x, so i'm not going to fix it. I guess you have a reason to stick with 1.x...

### Edit 2

fiddling around a bit more, i came up with a solution for Test 2 (without changing jQuery version).

The problem is, that jQuery uses `.innerHTML` in it's `append()` function. The fact that scripts not getting executed when inserted by `.innerHTML` is overcome by jQuery by `eval`ing the textContent of the script elements. jQuery does this based on script type (_which is absolutely correct, as there are script types out there that are not `eval`able_) But at the time jQuery was written, there was no `type="module"` ☹

So the script elements with `type="module"` do get inserted but not executed.

Knowing all this, the solution is again quite simple: get all scripts with `type="module"`, create a new script element, copy the textContent over, and replace the old script with the new script.

after line 64 (`$("body").append(nodeConfigEls);`)

```auto
nodeConfigEls[0].querySelectorAll( 'script[type="module"]' ).forEach( function ( item ) {
  var newScript = document.createElement( 'script' )
  newScript.appendChild( document.createTextNode( item.textContent ) )
  newScript.setAttribute( 'type', 'module' )
  item.parentNode.replaceChild( newScript, item )
})

```

This allows script `type="module"` in node configs everywhere. That means to use esm modules one can simply import them from the config script:

```auto
<script type="module">
    import { foo } from 'bar'
    RED.nodes.registerType(...bla bla bla)
</script>

```

### Edit 4

the simplest would be to use

`document.body.appendChild(nodeConfigEls[0])`

but that does not work... i have to investigate further...

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [29 April 2019 11:13 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/14 "2019-04-29T11:13:11Z")

</div>

Hi @Holger-Will - great work.

By coincidence, upgrading to jQuery 3.x is in the plan for Node-RED 1.0 - and I've spent the morning on that - [https://github.com/node-red/node-red/pull/2153](https://github.com/node-red/node-red/pull/2153) - so your workaround for that part wouldn't be needed. It isn't merged yet, but should be this week.

If you wanted to PR the other parts, we can review that. Please target the `dev` branch and not `master`.

---

<div class="post-metadata">

**Author:** ![kakyoism](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kakyoism/32/46283_2.png) [@kakyoism](https://discourse.nodered.org/u/kakyoism)\
**Post date:** [23 September 2022 09:48 UTC](https://discourse.nodered.org/t/include-js-in-a-html-custom-module/10434/15 "2022-09-23T09:48:19Z")

</div>

I still couldn't import module as in this thread using Node-RED version: v2.0.5.

My code in my\_node.html

```nohighlight
<!-- <script type="text/javascript"> -->
<script type="module">
    "use strict";
    import {foo} from './embedded.js';

```

The JS console error looks like this:

![Screen Shot 2022-09-23 at 17.46.22](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/1/31f11195f395d3fdac807b96f8d38e6470ff9421.png)

Is this still not officially supported?
