Pesquisa de site

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.

  1. `moduleResolution: "NodeNext"
  2. 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.

  1. ~$ sudo npm i -g typescript@next/Instalação Global

  2. ~$ 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;
}

Artigos relacionados