-
Notifications
You must be signed in to change notification settings - Fork 188
Description
Step to reproduce
- Create a new project, install jake
- Add the follow in package.json:
"type": "module" - Write the following Jakefile.js
import fs from 'fs';
task('default', () => {
console.log('Task ran');
});- Run jake:
./node_modules/.bin/jake - The following error is displayed
jake aborted.
Error [ERR_REQUIRE_ESM]: require() of ES Module .../jakefile.js from .../node_modules/jake/lib/loader.js not supported.
Instead change the require of jakefile.js in .../node_modules/jake/lib/loader.js to a dynamic import() which is available in all CommonJS modules.
at loadFile (.../node_modules/jake/lib/loader.js:67:20)
at Loader.loadFile (.../node_modules/jake/lib/loader.js:141:7)
at EventEmitter.Object.assign.run (.../node_modules/jake/lib/jake.js:315:37)
at Object.<anonymous> (.../node_modules/jake/bin/cli.js:31:10)
Investigation
It seems the problem is that the Jakefile is loaded via the old, synchronous require() call. Offending line:
In Jake source code, lib/loader.js:66
function loadFile(filePath) {
let exported = require(filePath); // <------ Problem here
for (let [key, value] of Object.entries(exported)) {
let t;
if (typeof value == 'function') {
t = jake.task(key, value);
t.description = '(Exported function)';
}
}
}Node.js does not support importing an ES6 module with this call, only commonjs module.
Potential fix
The fix is to use an asynchronous import() expression, which can import ES6 module from commonjs. However, that would making the function loadFile() and all its caller asynchronous, so its not a one line replacement.
Import expression: https://nodejs.org/dist/latest-v16.x/docs/api/esm.html#import-expressions
There is a little guide explaining the details here: https://techsparx.com/nodejs/esnext/esmodules-from-commonjs.html
Workaround
You can rename the Jakefile.js to Jakefile.cjs and rewrite it to use commonjs import
fs = require('fs');
task('default', () => {
console.log('BUILD DONE');
});
You will need to specify the jakefile explicitely : ./node_modules/.bin/jake -f Jakefile.cjs
Of course, if you import any ES6 module from Jakefile.cjs, you will need to use import expression, which can be cumbersome to use.