swc icon indicating copy to clipboard operation
swc copied to clipboard

spack: `jsc.paths` are not relative to `jsc.baseUrl`

Open evanw opened this issue 3 years ago • 10 comments

Describe the bug

I just tried using jsc.paths and jsc.baseUrl now that #1943, #2050, #2126, and #2523 have been closed by #2712 and a new release has been published. But it still doesn't appear to be working. Here's a reduced test case:

  • index.ts:

    import { foo } from 'foo/foo'
    console.log(foo)
    
  • foo/foo.ts:

    import { bar } from 'bar/bar'
    export let foo = 'foo' + bar
    
  • bar/bar.ts:

    export let bar = 'bar'
    
  • tsconfig.json:

    {
      "compilerOptions": {
        "baseUrl": "./",
        "paths": {
          "bar/bar": [
            "./bar/bar.ts"
          ],
          "foo/foo": [
            "./foo/foo.ts"
          ],
        },
      }
    }
    
  • spack.config.js:

    module.exports = {
      "options": {
        "jsc": {
          "baseUrl": "./",
          "paths": {
            "bar/bar": [
              "./bar/bar.ts"
            ],
            "foo/foo": [
              "./foo/foo.ts"
            ],
          },
        },
      },
      "entry": {
        "web": "index.ts",
      },
      "output": {
        "path": "out",
      },
    }
    

Input code

No response

Config

No response

Playground link

No response

Expected behavior

The example code compiles fine with tsc:

$ tsc -noEmit

So I expect it to also work with spack. But the example code fails to be bundled by spack:

$ spack
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

[Error: load_transformed failed

Caused by:
    0: failed to analyze module
    1: failed to resolve ./bar/bar from foo/foo.ts
    2: not processed by tsc resolver because it's relative import
    3: index not found] {
  code: 'GenericFailure'
}

It looks like spack is not treating paths as being relative to baseUrl. If I change spack.config.js to use a path starting with ../ then it succeeds, presumably because ../bar/bar.ts relative to ./foo/foo.ts is ./foo/../bar/bar.ts which gives you ./bar/bar.ts:

--- a/spack.config.js
+++ b/spack.config.js
@@ -4,7 +4,7 @@ module.exports = {
       "baseUrl": "./",
       "paths": {
         "bar/bar": [
-          "./bar/bar.ts"
+          "../bar/bar.ts"
         ],
         "foo/foo": [
           "./foo/foo.ts"

However, that behavior differs from how tsconfig.json behaves. The documentation for spack indicates that jsc.paths is supposed to behave like tsconfig.json: https://swc.rs/docs/configuration/compilation#jscpaths. So I assume this means it's a bug in spack. The paths in the config file should be relative to baseUrl, not to the directory containing the importing file.

Version

@swc/cli: 0.1.51, @swc/core: 1.2.108

Additional context

Using ../ instead of ./ as described above is not a valid workaround because the bug is that the path alias is being evaluated relative to the containing directory, which means that for large projects there will be no one relative path alias that works with all potential directories that code might import the path from.

One workaround that I discovered which did work is to use absolute paths instead:

--- a/spack.config.js
+++ b/spack.config.js
@@ -1,13 +1,13 @@
 module.exports = {
   "options": {
     "jsc": {
-      "baseUrl": "./",
+      "baseUrl": __dirname + "/",
       "paths": {
         "bar/bar": [
-          "./bar/bar.ts"
+          __dirname + "/bar/bar.ts"
         ],
         "foo/foo": [
-          "./foo/foo.ts"
+          __dirname + "/foo/foo.ts"
         ],
       },
     },

That could help avoid this issue until it's fixed.

evanw avatar Nov 11 '21 17:11 evanw

Does this issue is solved now ?

JulienKode avatar Dec 22 '21 15:12 JulienKode

It looks to me like it works as expected in .swcrc, but not when the config is passed in via JavaScript.

evantd avatar Feb 26 '22 05:02 evantd

You can pass absolute path if you are using js

kdy1 avatar Feb 26 '22 06:02 kdy1

You can pass absolute path if you are using js

this doesnt work on windows, it always add "./' before the path and didnt normalize the path

aelbore avatar May 21 '22 07:05 aelbore

This stopped working for me recently. I'm not sure what changed.

It should work just like TypeScript.

{ baseUrl: 'src', paths: {'#src/*': './src/*'} }

When I use transformSync it is using the cwd when I put . for baseUrl.

See also: https://github.com/swc-project/swc/issues/1388


The workaround suggested to use absolute paths, but this is such a perf killer, as I have to generated a new config for every project in my monorepo, and have to search upwards for the project root for every single file.

vjpr avatar Jun 15 '22 15:06 vjpr

@vjpr which OS you are using? I'm using mac os and it works fine I think I experience this issue on windows machine

aelbore avatar Jun 16 '22 14:06 aelbore

Note that DOS path .. maps to POSIX equivalent of ./ .NET reference docs on DOS paths; I wonder if the handling of paths cross platform is working properly via .swcrc...

riledigital avatar Sep 12 '22 15:09 riledigital

I also just got hit by this bug but it's not related to spack. The transformer API from core also triggers the same bug

alfaproject avatar Dec 13 '23 17:12 alfaproject

Hi @evanw @alfaproject, looks like it has been fixed on #8662. Could you check if it is resolved?

P.S. The baseUrl must be an absolute path.

devjiwonchoi avatar Feb 28 '24 14:02 devjiwonchoi

Sorry, I ended up using rspack for what I wanted to do and no longer have that problematic piece of code ):

alfaproject avatar Feb 28 '24 15:02 alfaproject