Closed HommeSauvage closed 4 months ago
cc @Brooooooklyn
This is a path alias in project references scenario, can you try https://www.typescriptlang.org/docs/handbook/project-references.html?
The following pointing path alias outside of the project does not work.
internal/tsconfig.json:
"paths": {
"@app/*": ["../apps/bar/*"]
},
I did that, here's the new tsconfig:
{
"extends": "../packages/tsconfig/base.json",
"compilerOptions": {
"baseUrl": ".",
"rootDir": "..",
"paths": {
"@app/*": ["../apps/bar/*"]
},
},
"include": [
"../apps/bar/**/*.ts",
"**/*.ts",
],
"references": [
{
"path": "../apps/bar"
}
],
}
And I added "composite": true
to apps/bar/tsconfig.json
. This did not change anything.
@HommeSauvage you can omit the SWCRC=true
from your command, you don't need a swcrc
file since you already have tsconfig files, @swc-node
can read configs from tsconfig.json
files and pass it to SWC.
Aha, when I removed SWCRC=true
, it seems like it was able to compile the first file, which is foo.ts
. But now, it's unable to resolve other
which is imported as import { other } from '@app/functions/other'
from within hello.ts
.
I pushed the changes to the reproduction repo. I added there vite
which is able to resolve everything correctly. ts-node had the same issue.
node:internal/modules/run_main:115
triggerUncaughtException(
^
Error: Cannot find module '@app/functions/other': @app/functions/other cannot be resolved in file://path/project/path-reproduction/apps/bar/functions/hello.ts
at resolve (file://path/project/path-reproduction/node_modules/.pnpm/@swc-node+register@1.10.3_@swc+core@1.6.13_@swc+helpers@0.5.11__@swc+types@0.1.9_typescript@5.5.3/node_modules/@swc-node/register/esm/esm.mjs:222:15)
at async nextResolve (node:internal/modules/esm/hooks:750:22)
at async Hooks.resolve (node:internal/modules/esm/hooks:238:24)
at async MessagePort.handleMessage (node:internal/modules/esm/worker:199:18)
Node.js v22.3.0
Try remove this because aliasing to files outside of the project is not supposed to work.
"paths": {
"@app/*": ["../apps/bar/*"]
},
Since you already specified https://github.com/DriveFlux/swc-path-issue/blob/a5ea7dbf11f5e13b496713eb76ce3781d24f1916/apps/bar/tsconfig.json#L6-L9
Well, that wouldn't make the files inside internal
folder able to resolve @app/functions/hello
.
The reason I have 2 tsconfig.json in those projects specifying paths is:
apps/bar
is supposed to be a NextJS app (or other kinds of apps), with its owntsconfig.json
, baseUrl
and paths
and it's part of the workspace (defined in pnpm-workspace.yaml
)
internal
is outside of the scope of the workspace, it's supposed to be able to import from various packages, including the apps/bar
app for some terminal commands, for example, manually executing a function that's also being used in the API of the app. That's why I define a tsconfig.json
inside of it to be able to resolve different packages.
If I remove paths
from internal/tsconfig.json
, the foo.ts
won't resolve hello.ts
. But by keeping it, it resolves @app/functions/hello.ts
, the hello.ts
is not able to resolve its sibling other.ts
which is in the same folder and is imported as @app/functions/other
.
diff --git a/internal/tsconfig.json b/internal/tsconfig.json
index be46d71..65c0af7 100644
--- a/internal/tsconfig.json
+++ b/internal/tsconfig.json
@@ -2,14 +2,16 @@
"extends": "../packages/tsconfig/base.json",
"compilerOptions": {
"baseUrl": ".",
"rootDir": "..",
"paths": {
- "@app/*": ["../apps/bar/*"]
+ "@app/*": ["../apps/bar/*"] // makes path alias work in this directory
},
},
+ "references": [{
+ "path": "../apps/bar/tsconfig.json" // makes path alias work in the other directory
+ }],
"include": [
"../apps/bar/**/*.ts",
"**/*.ts",
],
"ts-node": {
"transpileOnly": true,
@@ -23,4 +25,4 @@
}
}
}
}
This makes it work.
To understand what's going on in here, it goes all the way to how oxc-resolver has a builtin automatic project references path alias lookup mechanism ported from https://github.com/dividab/tsconfig-paths-webpack-plugin?tab=readme-ov-file#references-_string-defaultundefined
Aha, what I was missing was the tsconfig.json
in references
. The way I did it was:
"references": [
{
"path": "../apps/bar" // without tsconfig.json
}
],
Thanks @Boshen and @Brooooooklyn
Describe the bug
When using SWC (through @swc-node/register) in an ESM environment (
"type": "module"
) SWC seems to mess up the paths when resolving modules.In order to do so, create a monorepo and try to resolve files from different packages using "paths" settings in tsconfig.json and .swcrc.
Input code
Config
Playground link (or link to the minimal reproduction)
https://github.com/DriveFlux/swc-path-issue
SWC Info output
Operating System: Platform: darwin Arch: x64 Machine Type: x86_64 Version: Darwin Kernel Version 23.5.0: Wed May 1 20:09:52 PDT 2024; root:xnu-10063.121.3~5/RELEASE_X86_64 CPU: (16 cores) Models: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Strange that
swcrc path
is N/A. It's at the root as you may notice in the reproduction repo.Expected behavior
SWC should be able to follow baseUrl and resolve paths correctly.
Actual behavior
SWC adds many
../../../
into the pathVersion
1.6.13
Additional context
To run the reproduction:
pnpm internal
script and see the errorNotice that we register SWC this way:
cross-env SWCRC=true TS_NODE_PROJECT=./internal/tsconfig.json node --import @swc-node/register/esm-register
The
.swcrc
is at the root, pointing to the right paths and settingbaseUrl
to be the root. Thetsonfig.json
is inside theinternal
folder and sets thebaseUrl
to internal folder but sets the paths correctly.The use-case of this is to have many packages and apps in the repository and also an
internal
folder which is intended for terminal use only for quick scripts. Files in theinternal
folder should be able to execute JS from all the monorepo.We also use
@swc-node/register@1.10.3
which supports"moduleResolution": "Bundler"
.We use
Node: v22.3.0
I also tried to debug
@swc-node/register
and found that it correctly passes all the information to the compiler. The rust compiler then messes the path and returns the compiled file with those../../../