node.js - Typescript/Node Erro [ERR_MODULE_NOT_FOUND]: Não é possível encontrar o módulo
Convertendo projeto de CJS para ESM
Estou tentando converter meu projeto atual TypeScript-Node de ESM para CJS, no entanto, continuo recebendo o erro abaixo
Error [ERR_MODULE_NOT_FOUND]: Cannot find module` 'redacted/dist/config/datadog'
imported from /redacted/dist/app.js
É assim que a importação aparece em app.ts:
import './config/datadog';
E é assim que fica para app.js
import './config/datadog';
Aqui está o meu documento datadog.ts
datadog.ts
import tracer from 'dd-trace';
tracer.init({
logInjection: true,
profiling: true,
appsec: true
});
export default tracer;
Aqui está a impressão completa do erro que estou recebendo ao executar o aplicativo 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
Funciona bem ao rodar usando ts-node
node --experimental-specifier-resolution=node --loader ts-node/esm app.ts --project tsconfig.json
Eu configurei meu arquivo tsconfig.json assim:
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"lib": ["ES2020"],
"moduleResolution": "node",
"esModuleInterop": true,
"rootDir": "./src",
"outDir": "./dist",
"forceConsistentCasingInFileNames": true,
"strict": true,
}
}
Resposta #1
Você precisa usar o TypeScript v4.7, que atualmente é a versão TS-Next
Uma vez que você atualize para typescript@next, o que pode ser feito executando o comando ~/$ npm install -D typescript@next, você precisará fazer as alterações abaixo no seu arquivo tsconfig.json.
{
"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,
}
}
Para resumir
Você deve definir as chaves tsconfig.json module e moduleResolution como mostrado abaixo.
- `moduleResolution: "NodeNext"
module: "NodeNext"
Você precisará do TypeScript v4.7
Pessoalmente, eu mantenho uma propriedade global, então abaixo mostro o comando para a instalação global, mas tudo o que você realmente precisa é adicioná-la ao seu diretório node_modules como uma dependência para o seu projeto atual.
~$ sudo npm i -g typescript@next/Instalação Global~$ npm i -D typescript@next /Adicionar como uma dependência do projeto
Não posso ajudar com todos os IDEs existentes, mas se você usar o VSCode, use a seguinte configuração para que seu projeto use a versão v4.7.
Então você precisa definir a seguinte configuração
"typescript.tsdk": "./node_modules/typescript/lib",
package.json
Você também precisa habilitar ESM no Node. Para fazer isso, você precisa adicionar o seguinte ao seu package.json
/** @file "package.json" */
{
"type": "module"
}
...OU VOCÊ PODE usar a extensão de arquivo dot MTS (.mts) para todos os seus arquivos. Existem vantagens em ambos, mas discutir as vantagens está além do escopo desta resposta.
Isso deve ser tudo. Parece difícil, mas na verdade é fácil uma vez que você já tenha feito antes.
Para outra fonte útil:
A resposta neste LINK cobre o mesmo assunto com um pouco mais de detalhes. Eu realmente sugiro que você confira.
Resposta #2
A partir de julho de 2023
Eu não tentei atualizar meu TypeScript para a versão ts-next, mas esta solução funcionou para mim no TypeScript v5.1:
Basta adicionar .js ao final do nome do arquivo nas instruções de importação, como explicado aqui.
Exemplo:
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;
}
