Error: Not Supported
Node 12.x
If you are working with Node.js 12.x which adds full ESModule support, you may find you run into this error. This occurs using async dynamic ESModule loading (which is recommended to load ESModules .mjs
into CommonJS .cjs
code).
x.cjs
import('./myESModule.mjs').then(({ addRow }) => {
addRow('rockerBOO')
})
Node 13.2
What I would suggest is upgrading to Node.js 13.2, which has much better error messages. (sort-of)
TypeError: Invalid host defined options
at module.exports (./webpack.config.cjs:3:33)
TypeError [ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING]: A dynamic import callback was not specified.
at exports.importModuleDynamicallyCallback (internal/process/esm_loader.js:35:9)
How to fix?
Not sure yet. I think some of the tooling surrounding node.js is a little outdated and making it very complicated to integrate ESModules into their configuration process. For instance, right now, Webpack only supports CommonJS modules as it loads all config files (or all js files) through require
.
webpack.config.cjs
module.exports = new Promise($export => {
import('./webpack.config.mjs').then(config => {
$export(config)
})
})
This should allow a promise to return the config from a ESModule adjancent but I get one of these errors.
(node:2964) UnhandledPromiseRejectionWarning: TypeError: Invalid host defined options
at C:\...\webpack.config.cjs:4:2
at new Promise (<anonymous>)
at Object.<anonymous> (C:\...\webpack.config.cjs:3:18)
$ node -v
v13.2.0
An hour later
So later I learned from this webpack-cli
commit that -r @std/esm
is an option to preload the @std/esm
module before loading the webpack config. @std/esm
is superceded by esm
, -r esm
.
Using this I was able to try some more options and eventually got ESM to work load my ESModule config through a small CommonJS Loader.
module.exports = async (env, argv) => {
const config = await import('./webpack.config.mjs');
return config.default(env, argv)
}
One thing to note is if you import from a ESModule into a CommonJS file, you will need to use the named parameters.
const { default } = await import('./webpack.config.mjs')
But of course that doesn’t work. default
is a special keyword.
const config = await import('./webpack.config.mjs')
return config.default(env, argv)
So then I figure, what happens if I remove the -r esm
. And, well, it just worked.
webpack.config.mjs
const config = (env, argv) => {
return {
entry: ...,
...
}
}
export default config
Future
There is currently talks (as of 5 days ago) to allow .mjs
support natively in webpack-cli
node 13.2 has been released with .mjs support without flag: https://github.com/nodejs/node/releases/tag/v13.2.0
can we think about use webpack.config.mjs and webpack.config.cjs as config file?
Definitely, …