Kiran Mali
Kiran Mali

Reputation: 657

node-config Error [ERR_REQUIRE_ESM]: Must use import to load ES Module /default.js

I am using ESM in my node project. Added "type": "module" in package.json

// index.js

import config from 'config'
// default.js

export default {
  time: 123,
  ...
  ...
}

But getting error in node-config

Error: Cannot parse config file: '/home/Documents/.../config/default.js': Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/Documents/.../config/default.js
require() of ES modules is not supported.
require() of /home/Documents/.../config/default.js from /home/Documents/.../node_modules/config/parser.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename default.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/Documents/.../package.json.

I can fix this by adding default.cjs instead of default.js but as I am using ESM so I am expecting it to work with .js extension also. am I missing something??. I can add .json also but I have big config variables and dynamic values that is why using .js.

Thank you in advance !!!

Upvotes: 2

Views: 4192

Answers (1)

dotnetCarpenter
dotnetCarpenter

Reputation: 11281

According to https://github.com/node-config/node-config/wiki/Special-features-for-JavaScript-configuration-files you can not use ESM for configuration files but must use one of the other supported formats.

Loading files as ESM is not yet supported. So .mjs or .js when "type":"module" or --experimental-modules will not work.

But there is a work-around. For example you could have the following structure, where dynamic.js is where you have big config variables and dynamic values:

.
├── config
│   ├── dynamic.js
│   └── test.cjs
├── index.js
├── node_modules
│   ├── config
│   ├── json5
│   └── minimist
├── package-lock.json
└── package.json

You must tell nodejs that you use esm. So in your package.json you will want to have:

{
  "scripts": {
    "start": "NODE_ENV=test node index.js"
  },
  "type": "module"
}

In the beginning of your index.js file, you want to import node-config.

import config from 'config';

const {default:configVariable} = await config.get('variable');

console.debug(configVariable.foo);

In the above case you could write "Hello World!" to your terminal if config/test.cjs and config/dynamic.js has the following:

'use strict'

module.exports = {
    variable: import('./dynamic.js')
}

test.cjs

export default {
    v1: 'var1',
    v2: 'var2',
    foo: 'Hello World!'
}

dynamic.js

The result of the above should then be:

$ npm start

> start
> NODE_ENV=test node index.js

Hello World!

Obviously, you can rename variable and configVariable to what-ever you want.

In my test, I had no issue with the above way of exporting esm as a Promise. But if you do get any issue with with that, you might solve it by wrapping import() in require('config/raw').raw. See: https://github.com/node-config/node-config/wiki/Special-features-for-JavaScript-configuration-files#using-promises-processstdout-and-other-objects-in-javascript-config-files.

Upvotes: 2

Related Questions