How can I dynamically import both commonJS and ES6 modules from the same node CLI?

2.7k views Asked by At

I have looked through many similar questions on SO, and haven't found a clear answer.

I'm writing an npm CLI tool which is supposed to dynamically import a specified module and run some operations on that module's exports.

In my npm package, I have specified "type": "module" and my binary is bin/generator.mjs.

The way I'm trying to use it is: ❯ ./bin/generator.mjs path/to/test-module.js [other args] - and then in the generator I do:

const modulePath = "file://" + path.resolve(inputFilename);
const objs = await import(modulePath);

With this configuration, I can specify an ES6 module on the command line, and the generator works fine, however, if I specify a CommonJS module, I get:

const Library = require('some-library');
                ^
ReferenceError: require is not defined

Here are my two test files:

ES6 module

import Library from 'some-library';

export const person = { firstName: "Bob", lastName: "Mortimer };

CommonJS module

const Library = require('some-library');

const person = { firstName: "Bob", lastName: "Mortimer };
module.exports.person = person;

So then I tried having two different binaries - generator for ES6 modules, and generator-cjs for CommonJS ones - I modified the original to use requires in place of import, however, the bin/generator.mjs continues to work fine, but the bin/generator.cjs throws this error:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: [...]/test-module.js
require() of ES modules is not supported.
require() of [...]/test-module.js from [...]/bin/generator.cjs 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 test-module.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from [...]/package.json.

If I remove "type": "module" from my package.json, both generator and generator-cjs work on CommonJS files, but generator throws this error on ES6 modules:

throw new Error('Unexpected import statement in CJS module.');
            ^
Error: Unexpected import statement in CJS module.

Ideally: I want to have one binary that can import both CommonJS and ES6 modules dynamically.

If you have read through this far - thank you.

Do you have any ideas on how I can resolve this? Let me know if you want me to try things to provide more information.

Thanks,


Edit: I should mention that converting the CommonJS modules to ES6 is not an option as there are nearly a hundred CJS ones, and they have complicated dependency chains that will take time to unravel.

0

There are 0 answers