Reputation: 2865
I am attempting to convert my current TypeScript-Node project from ESM to CJS, however, I keep getting the error below
Error [ERR_MODULE_NOT_FOUND]: Cannot find module` 'redacted/dist/config/datadog'
imported from /redacted/dist/app.js
app.ts
: import './config/datadog';
app.js
import './config/datadog';
datadog.ts
import tracer from 'dd-trace';
tracer.init({
logInjection: true,
profiling: true,
appsec: true
});
export default tracer;
Here is the full printout of the error I am recieving when I execute the app via ~/$ node dist/app.js
.
> node dist/app.js
node:internal/errors:465
ErrorCaptureStackTrace(err);
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'redacted/dist/config/datadog' imported from /redacted/dist/app.js
at new NodeError (node:internal/errors:372:5)
at finalizeResolution (node:internal/modules/esm/resolve:405:11)
at moduleResolve (node:internal/modules/esm/resolve:966:10)
at defaultResolve (node:internal/modules/esm/resolve:1176:11)
at ESMLoader.resolve (node:internal/modules/esm/loader:605:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:318:18)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:80:40)
at link (node:internal/modules/esm/module_job:78:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
Node.js v18.0.0
Process finished with exit code 1
It works fine When running using ts-node
node --experimental-specifier-resolution=node --loader ts-node/esm app.ts --project tsconfig.json
tsconfig.json
file like this: {
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"lib": ["ES2020"],
"moduleResolution": "node",
"esModuleInterop": true,
"rootDir": "./src",
"outDir": "./dist",
"forceConsistentCasingInFileNames": true,
"strict": true,
}
}
Upvotes: 18
Views: 30919
Reputation: 3443
I haven't tried updating my typescript to the ts-next
version, but this solution worked for me for Typescript v5.1:
Simply add .js
to the end of the filename on the import statements, as explained here.
Example:
# Folder structure
app/
controller/
mymodule.ts
index.ts
package.json
tsconfig.json
// package.json
{
"name": "project-name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module", // keep the module keyword
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
...
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"strict": true,
"esModuleInterop": true,
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"outDir": "./build",
"rootDir": "./app"
},
"exclude": ["node_modules"]
}
// index.ts
import userController from './controller/users.js'
userController.foo();
// mymodule.ts
const foo = async () => {
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
return 0;
}
Upvotes: 3
Reputation: 1
More insight:
Importing './env' only works in CJS.
Importing './env.mjs' is required in ESM.
Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './env.mjs'?ts(2835)
Upvotes: 0
Reputation: 11819
Once you upgrade to typescript@next
which can be done by executing the command ~/$ npm install -D typescript@next
, you will need to make the changes below to your tsconfig.json
file.
{
"compilerOptions": {
"lib": [
"ESNext" /* ESNext includes new Level-4 features that were
recently added to the ECMA-262 JS spec */
],
"module": "NodeNext",/* (1 of 2) TS v4.7 settings you need
to change */
"moduleResolution": "NodeNext", /* This is the one that will
specifically solve the error you're
getting. Without the internal changes
made by this, your project will not
resolve modules correctly. */
"esModuleInterop": true, /* This is properly configured. FYI you cannot
change this, it must be set to true. */
/*
THE REST OF THE SETTINGS DO NOT AFFECT THE MODULE TYPE OR HOW TSC
RESOLVES OTHER MODULES */
"target": "ES2021",
"rootDir": "./src",
"outDir": "./dist",
"forceConsistentCasingInFileNames": true,
"strict": true,
}
}
You must set the tsconfig.json
keys module
and moduleResolution
as they are shown below.
module: "NodeNext"
Personally I keep a global property, so below I show the command for the global install, but all you really need is to add it to your node_modules
dir it as a dependency for your current project.
~$ sudo npm i -g typescript@next // Global Install
~$ npm i -D typescript@next // Add as a Project Dependency
I can't help with ever IDE in existance, but if you use VSCode, use the following configuration so your project uses the ver v4.7.
Then you need to set the following configuration
"typescript.tsdk": "./node_modules/typescript/lib",
package.json
You also need to enable ESM in for Node.. To do this you need to add the following to your package.json
/** @file "package.json" */
{
"type": "module"
}
...OR YOU CAN use the dot MTS (.mts
) file extension for all of your files. There are advantages to both, but discussing the advantages is beyond the scope of this answer.
That should be it. It sounds hard but its actually easy once you have done it before.
The answer at this LINK covers this same subject with a bit more detail. I really suggest you check it out.
Upvotes: 15