Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot Find Module #157

Open
Lioness100 opened this issue Feb 6, 2021 · 22 comments
Open

Cannot Find Module #157

Lioness100 opened this issue Feb 6, 2021 · 22 comments

Comments

@Lioness100
Copy link

Lioness100 commented Feb 6, 2021

It seems my module paths do not get resolved correctly when using node or ts-node

src/index.ts

import cleanup from 'node-cleanup';
import ArimaClient from '@client/ArimaClient';

// ...

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2019",
    "lib": ["ES2019"],
    "moduleResolution": "node",
    "module": "commonjs",
    "strict": true,
    "alwaysStrict": true,
    "useDefineForClassFields": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "inlineSources": true,
    "esModuleInterop": true,
    "removeComments": true,
    "skipLibCheck": true,
    "baseUrl": ".",
    "outDir": "dist/",
    "typeRoots": ["node_modules/@types", "src/typings"],
    "paths": {
      "@root/*": ["src/*"],
      "@client/*": ["src/lib/client/*"],
      "@database/*": ["src/lib/database/*"],
      "@structures/*": ["src/lib/structures/*"],
      "@structures": ["src/lib/structures"],
      "@utils/*": ["src/lib/utils/*"],
      "@utils": ["src/lib/utils"]
    }
  },
  "include": ["src"]
}

Scripts (I get the same error for both)

ts-node --files src/index.ts -r dotenv/config -r tsconfig-paths/register NODE_ENV=dev
tsc && node -r dotenv/config -r tsconfig-paths/register .

Error

internal/modules/cjs/loader.js:883
  throw err;
  ^

Error: Cannot find module '@client/ArimaClient'
Require stack:
- C:\Users\me\OneDrive\Desktop\Arima\dist\index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.Module._resolveFilename (C:\Users\me\OneDrive\Desktop\Arima\node_modules\tsconfig-paths\lib\register.js:75:40)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (C:\Users\me\OneDrive\Desktop\Arima\dist\index.js:7:39)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ 'C:\\Users\\me\\OneDrive\\Desktop\\Arima\\dist\\index.js' ]
}
@lixaotec
Copy link

+1
same problem

@jacobq
Copy link

jacobq commented May 19, 2021

It looks like you are having the same problem that I'm currently having with this. What seems to be happening is that tsconfig-paths is looking at tsconfig.json's baseUrl but not taking outDir into consideration. I found this by manually editing the register function in node_modules/tsconfig-paths/lib/register.js so that it would log some debug info when trying to resolve my path mappings like this:

register.js
/**
 * Installs a custom module load function that can adhere to paths in tsconfig.
 * Returns a function to undo paths registration.
 */
function register(explicitParams) {
    // ...
    Module._resolveFilename = function (request, _parent) {
        var isCoreModule = coreModules.hasOwnProperty(request);
        if (!isCoreModule) {
            // DEBUG ___________________________
            if (request.indexOf('@src') === 0) {
              console.log(`_resolveFilename handling '${request}', configLoaderResult =`, configLoaderResult);
            }
            // DEBUG ^^^^^^^^^^^^^^^^^
            var found = matchPath(request);
            if (found) {
                var modifiedArguments = [found].concat([].slice.call(arguments, 1)); // Passes all arguments. Even those that is not specified above.
                // tslint:disable-next-line:no-invalid-this
                return originalResolveFilename.apply(this, modifiedArguments);
            }
        }
        // tslint:disable-next-line:no-invalid-this
        return originalResolveFilename.apply(this, arguments);
    };
    return function () {
        // Return node's module loading to original state.
        Module._resolveFilename = originalResolveFilename;
    };
}

The output from here was like this (build is what I've specified for outDir):

Failure shown in output
_resolveFilename handling '@src/util', configLoaderResult = {
  resultType: 'success',
  configFileAbsolutePath: 'C:\\project_root\\tsconfig.json',
  baseUrl: '.',
  absoluteBaseUrl: 'C:\\project_root',
  paths: { '@src/*': [ 'src/*' ] }
}
internal/modules/cjs/loader.js:883
  throw err;
  ^

Error: Cannot find module '@src/util'
Require stack:
- C:\project_root\build\src\foo.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.Module._resolveFilename (C:\project_root\node_modules\tsconfig-paths\lib\register.js:78:40)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (C:\project_root\build\src\foo.js:22:16)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    'C:\\project_root\\build\\src\\foo.js'
  ]
}

If I change baseUrl to match outDir (i.e. build for my example, dist for OP) after running tsc then tsconfig-paths gets it right. In my opinion, this is a bug, but it is possible to work around by adapting the "Bootstrapping with explicit params" example in the README.md.

What I did to make it work was replace node -r tsconfig-paths/register ... with node -r ./register-paths.js ... (and create register-paths.js as shown below). Basically this tells tsconfig-paths a different baseUrl that incorporates outDir.

`register-paths.js`
const path = require('path');
const tsConfig = require('./tsconfig.json');
const tsConfigPaths = require('tsconfig-paths');

const baseUrl = tsConfig.compilerOptions.baseUrl || '.';
const outDir = tsConfig.compilerOptions.outDir || '.';
const explicitParams = {
  baseUrl: path.resolve(baseUrl, outDir),
  paths: tsConfig.compilerOptions.paths,
};
const cleanup = tsConfigPaths.register(explicitParams);

// TODO: clean-up when path registration is no longer needed
//cleanup();

@zyf0330
Copy link

zyf0330 commented Jul 27, 2021

You can specify correct main in package.json

@VGavara
Copy link

VGavara commented Aug 31, 2021

+1 same problem

Another solution is defining a custom tsconfig file containing as baseUrl the out directory. This custom file must also contain the paths defined in the tsconfig file used for file emission. Only compilerOptions.baseUrl and compilerOptions.paths have to be defined. Those paths not being emitted (as directories containing tests or types) can be omitted.

Then this custom file (let's say it is called tsconfig-paths.json) can be set as the value of the env var TS_NODE_PROJECT just for the package.json run script in this way:

// package.json file
{
    "scripts": {
        "run": "TS_NODE_PROJECT=tsconfig-paths.json node -r tsconfig-paths/register dist/index.js",
    }
}

@JarnoRFB
Copy link

I have the same problem, based on the readme, I though setting TS_NODE_BASEURL should be the solution, but this has also no effect for me.

@ardyfeb
Copy link

ardyfeb commented Dec 3, 2021

@JarnoRFB yes, TS_NODE_BASEURL seems useless

@JarnoRFB
Copy link

JarnoRFB commented Dec 4, 2021

Actually I got it to work now using TS_NODE_BASEURL. I have a layout like

src/
  myscript.ts
  mymodule.ts
tsconfig.json

and im my tsconfig.json

"compilerOptions": {
    "outDir": "dist",
    "baseUrl": "src",
    "paths": {
      "@/*": ["./*"]
    },
  },
  "include": [
    "src"
  ],

Now when I put a script in my package.json like so

"scripts": {
    "myscript": "tsc --module 'CommonJS' && TS_NODE_BASEURL=./dist node -r tsconfig-paths/register dist/myscript.js",
}

I can run it with npm run myscript just fine with "@/mymodule" imports.

What didn't work before was when I had baseUrl and paths switched in tsconfig.json like

    "baseUrl": "./",
    "paths": {
      "@/*": ["./src"]
    },

@afonsomatos
Copy link

Actually I got it to work now using TS_NODE_BASEURL. I have a layout like

src/
  myscript.ts
  mymodule.ts
tsconfig.json

and im my tsconfig.json

"compilerOptions": {
    "outDir": "lib",
    "baseUrl": "src",
    "paths": {
      "@/*": ["./*"]
    },
  },
  "include": [
    "src"
  ],

Now when I put a script in my package.json like so

"scripts": {
    "myscript": "tsc --module 'CommonJS' && TS_NODE_BASEURL=./dist node -r tsconfig-paths/register dist/myscript.js",
}

I can run it with npm run myscript just fine with "@/mymodule" imports.

What didn't work before was when I had baseUrl and paths switched in tsconfig.json like

    "baseUrl": "./",
    "paths": {
      "@/*": ["./src"]
    },

What you share still doesn't work for me.

@JarnoRFB
Copy link

@afonsomatos Forgot to change outdir it was still set to lib instead of dist. Fixed it now, let me know if this helps.

@flleeppyy
Copy link

Any official patch for this instead of some hacky workaround?

@flleeppyy
Copy link

Oh nevermind this package looks dead.

@Adam1901
Copy link

Adam1901 commented Mar 15, 2022

I gave up after a while getting it working in production, using either ts-node or plain node or any other method.

I feel I found a nice solution though with using tscpaths. Which replaces the shornted paths in the dist folder at build time.

https://www.npmjs.com/package/tscpaths

package.json:

   "build": "tsc --project tsconfig.json && tscpaths -p tsconfig.json -s ./src -o ./dist",

    "dev": "nodemon -r tsconfig-paths/register src/index.ts dev", 

Dockerfile:

RUN npm i
....
RUN npm run build
...
CMD [ "node", "dist/index.js" ]

Hope this helps

@lbittner-pdftron
Copy link

lbittner-pdftron commented May 4, 2022

+1 this package is useless I think, time to find a different solution

EDIT: This package seems to work good for my use case https://github.com/justkey007/tsc-alias

@Lioness100
Copy link
Author

I ended up just using native paths with esm

@voinik
Copy link

voinik commented Aug 13, 2022

I gave up after a while getting it working in production, using either ts-node or plain node or any other method.

I feel I found a nice solution though with using tscpaths. Which replaces the shornted paths in the dist folder at build time.

https://www.npmjs.com/package/tscpaths

package.json:

   "build": "tsc --project tsconfig.json && tscpaths -p tsconfig.json -s ./src -o ./dist",

    "dev": "nodemon -r tsconfig-paths/register src/index.ts dev", 

Dockerfile:

RUN npm i
....
RUN npm run build
...
CMD [ "node", "dist/index.js" ]

Hope this helps

This package hasn't been updated since May 2019. I got it to work with my setup with some small configuration adjustments (I needed to set the output path to ./build/src instead of ./build).

However I suggest that people use the package @lbittner-pdftron mentioned (thanks for the tip!) as it's still being maintained and I got that to work with 0 configuration. Just add && tsc-alias -p tsconfig.json to your tsc build script and it should work. Your mileage may vary depending on how complex your project is.

@mirajehossain
Copy link

well, after suffering a few hours, I got a solution
I have used the ts-node package, and I got the same error Error: Cannot find module '@modules/logger'

You need to add ts-node configuration in the tsconfig.json file.
You can get more infor at ts-node

{
    "ts-node": {
        // Do not forget to `npm i -D tsconfig-paths`
        "require": ["tsconfig-paths/register"]
    },
    "compilerOptions": {
        "lib": ["es5", "es6", "es7"],
        "target": "es2017",
        "module": "commonjs",
        "moduleResolution": "node",
        "rootDir": "src",
        "outDir": "build",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "esModuleInterop": true,
        "noImplicitAny": true,
        "strict": true,
        "resolveJsonModule": true,
        "allowJs": true,
        "sourceMap": true,

        "baseUrl": ".",
        "paths": {
            "@modules/*": ["src/modules/*"],
            "*": ["node_modules/*"]
        },

    },
    "include": ["src/**/*"]
}

@wvhulle
Copy link

wvhulle commented Dec 8, 2022

"ts-node": {
// Do not forget to npm i -D tsconfig-paths
"require": ["tsconfig-paths/register"]
},

This doesn't work for me

@iandoesallthethings
Copy link

This doesn't work for me

Same, still seems broken.

@mirajehossain
Copy link

This doesn't work for me

Same, still seems broken.

can you try wiith import the module-alias dependency in your entry file import 'module-alias/register';

@impuLssse
Copy link

thanx

@Patryk-B
Copy link

Patryk-B commented Oct 1, 2023

i know this is an old issue, but i recently stumbled onto it myself.
I believe i found a workaround:

Relevant configuration:

directory structure:

/

/dist/src/foo/...
/dist/src/foo.js

/dist/test/foo/integration/...
/dist/test/foo/unit/...

/src/foo/...
/src/foo.ts

/test/foo/integration/...
/test/foo/unit/...

THE MAIN OFFENDER: package.json:

{
    "imports": {
        "#src/*": "./dist/src/*",
        "#test/*": "./dist/test/*"
    },
}

tsconfig.json:

{
    "include": [
        "src/**/*",
        "test/**/*"
    ],
    "exclude": [
        "node_modules/**/*",
        "dist/**/*"
    ],
    "compilerOptions": {
        "rootDir": ".",
        "outDir": "./dist",
        "baseUrl": ".",
        "paths": {
            "#src/*": [ "src/*" ],
            "#test/*": [ "test/*" ]
        },
    }
}

Problem synopsis:

  • tsconfig-paths/register can't handle this particular case.
  • ts-node uses imports: { ... } from package.json rather then paths from tsconfig.json.
  • if "imports": { "#src/*": "./dist/src/*" } then NODE_ENV=dev code stops working. aka ts-node, nodemon, etc stops working, because /dist/ dir by definition doesn't exist in NODE_ENV=dev mode.
  • if "imports": { "#src/*": "./src/*" } then NODE_ENB=prod code stops working. aka node . bc *.js files reside in /dist/src/ dir. node simply doesn't see /src/dist/**/*.js code with path aliases directed to /src/ dir. Not to mention /src/ dir is populated with *.ts files.

Workaround:

  1. Create a 2nd package.json file in /dist/package.json:
{
    "imports": {
        "#src/*": "./src/*",
        "#test/*": "./test/*"
    },
}
  1. Rewrite original package.json in /package.json:
{
    "imports": {
        "#src/*": "./src/*",
        "#test/*": "./test/*"
    },
}

Explanation:

  • NODE_ENB=dev code resides in /src/ dir as *.ts files.
  • NODE_ENB=prod code resides in /dist/src/ dir as *.js files.
  • import: { ... } in /package.json configures how ts-node will resolve path aliases in /src dir, aka the NODE_ENB=dev code.
  • import: { ... } in /dist/package.json configures how node will resolve path aliases in /src/dist dir, aka the NODE_ENB=prod code.

I do not know if this workaround is foolproof. I can imagine problems when trying to publish a package with multiple package.json files. But haven't tested it yet.

Please leave a like if you found this workaround helpful 🙇🙇🙇🙇

@muhammadalitamanaee
Copy link

muhammadalitamanaee commented May 12, 2024

i get the similar err when i run the npx tsc --noEmit on the pre_commit file in the husky folder and the problem is i think it doesnt consider the compiler options that we defined on the tsconfig.json and doesnt learn the pthes.
i dont know what to do either , and i tried every solution in this issue.
the ts config and pre_commit is as follows:
tsconfig:
{ "compilerOptions": { "target": "es6", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "module": "ESNext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "baseUrl": ".", "paths": { "@components/*": [ "./src/components/*" ], "@hooks/*": [ "./src/hooks/*" ], "@layout/*": [ "./src/layouts/*" ], "@type/*": [ "./src/types/*" ], "@constants/*": [ "./src/constants/*" ], "@contexts/*": [ "./src/contexts/*" ], "@modules/*": [ "./src/modules/*" ], "@redux/*": [ "./src/redux/*" ], "@services/*": [ "./src/services/*" ], "@utils/*": [ "./src/utils/*" ], "@forms/*": [ "./src/components/forms/*" ] }, "plugins": [ { "name": "next" } ] }, "include": [ "./src/**/*.ts", "./src/**/*.tsx", "./app/**/*.ts", "./app/**/*.tsx", ".next/types/**/*.ts", "*" ], "exclude": [ "node_modules", ".next" ] }
and this is the .lintstagedrc:
{ "*.{ts,tsx}": ["eslint --fix", "prettier --write","tsc --noEmit --jsx preserve "] }
and pre_commit file :
. "$(dirname -- "$0")/_/husky.sh" npx lint-staged npx tsc --noEmit

any thing will be appreciated , im desperate mode right now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests