Skip to content

spack: jsc.paths are not relative to jsc.baseUrl #2725

@evanw

Description

@evanw

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions