I’m playing with NodeJS loaders where I want to intercept all calls to require
and modify the source (transpile). When using ESM modules with import
it works, but with CommonJS it doesn’t trigger the loader when calling require
.
Here is the loader code:
async function load(url, context, nextLoad) {
console.log({ url, context })
return nextLoad(url)
}
async function resolve(specifier, context, nextResolve) {
console.log({ specifier, context })
return nextResolve(specifier)
}
module.exports = { load, resolve }
I’m injecting the loader by running node --loader=./loader.js hello.js
from terminal.
And here is the CommonJS code for hello.js
:
var lib = require('./lib.js')
The require('./lib.js')
line neither triggers the loader resolve nor the load functions in the loader.
If I rewrite using ESM .mjs
and import
it works as expected.
Any ideas?
2
Answers
When using custom loaders with CommonJS, the files you require cannot only contain async functions, or the main thread might kill the hook thread before fully loading the file. This is from the documentation:
This isn't reached when required from the main thread:
but this works:
or any other synchronous code. In long running applications, like a web server application, it will also work without issues.
Loaders in Node.js for ECMAScript Modules (ESM) and CommonJS modules. The loader you have defined works with ESM imports, but it doesn’t automatically handle CommonJS require calls because they use a different mechanism for module resolution and loading.
If I didn’t wan’t to use a build tool, I would use Node.js’s require hook mechanism; but it’s more complex and less flexible IMHO.