# How to use ESM only modules in Custom Nodes?

**URL:** <https://discourse.nodered.org/t/how-to-use-esm-only-modules-in-custom-nodes/97240>\
**Category:** General\
**Created:** [23 May 2025 21:31 UTC](https://discourse.nodered.org/t/how-to-use-esm-only-modules-in-custom-nodes/97240 "2025-05-23T21:31:36Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [23 May 2025 21:31 UTC](https://discourse.nodered.org/t/how-to-use-esm-only-modules-in-custom-nodes/97240/1 "2025-05-23T21:31:36Z")

</div>

Because aws-cdk-lib v2 is esm only, the only way I was able to make Node-RED load it was using esbuild to bundle it together with my authored source code. Is there another option?

When I configure esbuild to avoid bundling aws-cdk-lib, esbuild uses `require` with it and it doesn't work because it is an esm only module. Can Node-RED run an esm build? How can I do it?

I can't have an esm build because then I'm required to use "type": "module" in my custom node package.json because I get this runtime error

Node 18

```bash
23 May 19:01:11 - [warn] [node-red-custom-nodes/nodes] Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/allanoricil/node-red-custom-nodes/dist/index.js from /Users/allanoricil/.nvm/versions/node/v18.18.0/lib/node_modules/node-red/node_modules/@node-red/registry/lib/loader.js not supported.

```

Node 22

```bash
23 May 19:03:17 - [warn] [node-red-custom-nodes/nodes] Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'aws-cdk-lib' imported from /Users/allanoricil/node-red-custom-nodes/dist/index.js

```

The above message for Node 22 is weird because I can see `aws-cdk-lib` package in `~/.node-red/node_modules`

The `aws-cdk-lib` package is located in `~/.node-red`. Neither `require` nor `import` can find it at runtime. What could it be?

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/0/00689b1c6f59c1668cb24e0ff63843022c4824a3.png)

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 May 2025 22:02 UTC](https://discourse.nodered.org/t/how-to-use-esm-only-modules-in-custom-nodes/97240/2 "2025-05-23T22:02:56Z")

</div>

Node-RED can use ESM modules in function nodes.

But for custom nodes, it is more complex and I've still not mastered it. That's because Node-RED is largely CommonJS throughout and so the only way to load an ESM is via the import function which is async.

Thankfully, node.js are finally fixing the ridiculous situation they've allowed to continue for years and give the flexibility to properly load ESM from CommonJS. But that isn't yet live and so probably won't appear in Node-RED until v5.

It would be great to see a way to move custom nodes to ESM, hopefully someone has a clever way.

In the meantime, I do what you are, use ESBUILD to transcribe from ESM to CommonJS where needed. Though honestly, using ESBUILD with node.js modules is a bit of a pain I think and I have no incentive yet to migrate much. I mostly use ESBUILD for front-end code to allow the use of newer JS but build for older browsers.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [23 May 2025 22:17 UTC](https://discourse.nodered.org/t/how-to-use-esm-only-modules-in-custom-nodes/97240/3 "2025-05-23T22:17:28Z")

</div>

@TotallyInformation Thank you.  
Do you know why Node 22 works with esm but can't find the package still? That is what can't understand. The package is installed in my userDir.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 May 2025 22:45 UTC](https://discourse.nodered.org/t/how-to-use-esm-only-modules-in-custom-nodes/97240/4 "2025-05-23T22:45:11Z")

</div>

Not sure - is there a node.js version clash? I would have thought it would be a specific error for that.

---

<div class="post-metadata">

**Author:** ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)\
**Post date:** [24 May 2025 20:08 UTC](https://discourse.nodered.org/t/how-to-use-esm-only-modules-in-custom-nodes/97240/5 "2025-05-24T20:08:04Z")

</div>

I gave up. Using esbuild again. The sadest thing is that, even after tree shaking, I ended up with a 31.3 MB index.js

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/f/7f2d68f8953adf566eacd5305fd75b8aef9ea886.png)

I managed to tree shake a little bit more

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/d/1d0759cd843ba6dbd477493f243296ee67e22c59.png)

In my case it won't be a problem because these nodes will be part of the core shipped with a custom docker image.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [7 June 2025 20:08 UTC](https://discourse.nodered.org/t/how-to-use-esm-only-modules-in-custom-nodes/97240/6 "2025-06-07T20:08:16Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
