tsconfig-paths
tsconfig-paths copied to clipboard
Cannot Find Module
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' ]
}
+1 same problem
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();
You can specify correct main in package.json
+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",
}
}
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.
@JarnoRFB yes, TS_NODE_BASEURL seems useless
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"]
},
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
andpaths
switched in tsconfig.json like"baseUrl": "./", "paths": { "@/*": ["./src"] },
What you share still doesn't work for me.
@afonsomatos Forgot to change outdir
it was still set to lib
instead of dist
. Fixed it now, let me know if this helps.
Any official patch for this instead of some hacky workaround?
Oh nevermind this package looks dead.
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
+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
I ended up just using native paths with esm
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.
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/**/*"]
}
"ts-node": { // Do not forget to
npm i -D tsconfig-paths
"require": ["tsconfig-paths/register"] },
This doesn't work for me
This doesn't work for me
Same, still seems broken.
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';
thanx
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
usesimports: { ... }
frompackage.json
rather thenpaths
fromtsconfig.json
. - if
"imports": { "#src/*": "./dist/src/*" }
thenNODE_ENV=dev
code stops working. akats-node
,nodemon
,etc
stops working, because/dist/
dir by definition doesn't exist inNODE_ENV=dev
mode. - if
"imports": { "#src/*": "./src/*" }
thenNODE_ENB=prod
code stops working. akanode .
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:
- Create a 2nd
package.json
file in/dist/package.json
:
{
"imports": {
"#src/*": "./src/*",
"#test/*": "./test/*"
},
}
- 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 howts-node
will resolve path aliases in/src
dir, aka theNODE_ENB=dev
code. -
import: { ... }
in/dist/package.json
configures hownode
will resolve path aliases in/src/dist
dir, aka theNODE_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 🙇🙇🙇🙇