When you write a Node.js application using TypeScript, the default configuraion will treat the ESM package as CommonJS package, just like this:
// before compile
import execa from 'execa'
execa("openssl")
// after compile
var execa_1 = require("execa");
(0, execa_1.execa)('openssl');
No errors are reported during compilation, but errors are reported at runtime:
Error [ERR_REQUIRE_ESM]: require() of ES Module not supported.
This article tell you how to configure your project to make pure ESM package work.
Configure TypeScript
open tsconfig.json
in your project, set the compilerOptions.module
to NodeNext
, after this, js files generated by tsc/ts-node will use import instead of require.
However, since the default configuration of Node.js only supports synchronous module imports, TypeScript also takes this into account and does not compile the import statement, you will still get an error using the import statement, and you have to use dynamic imports, like this:
; (async () => {
const { execa } = (await import('execa'))
execa('openssl')
})()
It's terrible, but there is help, we just need to change the configuration of Node.js, and then TypeScript will see it and allow us to use the import statement.
Configure Node.js
The default configuration of Node.js also don't support ESM package, use import
in .js file will throw errors:
import { execa } from 'execa'
(node:2164) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
SyntaxError: Cannot use import statement outside a module
The output of Node.js already indicates what we need to do, just open package.json
and add a new property:
"type": "module"
Run it again and it works fine.
All done.