bazelbuild/rules_nodejs

`rootDirs` workaround does not work as documented

jfirebaugh opened this issue ยท 3 comments

๐Ÿž bug report

Affected Rule

The issue is caused by the rule: ts_project

Is this a regression?

No

Description

The documentation for ts_project describes how to set the rootDirs compiler option so that TypeScript can resolve relative references to the bazel-out folder. However, this doesn't work as documented in seemingly simple cases. For example, a project with subdirectories a and b containing respective ts_projects, where a depends on b. Based on the documentation, a's tsconfig.json should contain:

    "rootDirs": [
      ".",
      "../bazel-out/host/bin/a",
      "../bazel-out/darwin-fastbuild/bin/a",
    ]

(Paths for additional host architectures omitted because I'm testing solely on macOS.)

๐Ÿ”ฌ Minimal Reproduction

https://github.com/jfirebaugh/rules_nodejs_test

๐Ÿ”ฅ Exception or Error

a/a.ts(1,19): error TS2307: Cannot find module '../b/b' or its corresponding type declarations.

๐ŸŒ Your Environment

Operating System: macOS
Output of bazel version:

  
Build label: 5.0.0-homebrew
Build target: bazel-out/darwin-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Tue Jan 1 00:00:00 1980 (315532800)
Build timestamp: 315532800
Build timestamp as int: 315532800
  

Rules_nodejs version:

(Please check that you have matching versions between WORKSPACE file and @bazel/* npm packages.)

  
5.4.0
  

Anything else relevant?

The following patch allows the project to build successfully, but is contrary to what the documentation suggests:

diff --git a/a/tsconfig.json b/a/tsconfig.json
index 99f2666..ccc45c9 100644
--- a/a/tsconfig.json
+++ b/a/tsconfig.json
@@ -3,9 +3,9 @@
     // https://bazelbuild.github.io/rules_nodejs/TypeScript.html#ts_project
     // https://github.com/microsoft/TypeScript/issues/37378
     "rootDirs": [
-      ".",
-      "../bazel-out/host/bin/a",
-      "../bazel-out/darwin-fastbuild/bin/a",
+      "..",
+      "../bazel-out/host/bin",
+      "../bazel-out/darwin-fastbuild/bin",
     ]
   }
 }

If anyone who has worked on this issue has suggestions on how to debug this when it happens, I'd really appreciate it. Every now and then something breaks with this feature and I lose a lot of time trying to guess what combination of rootDirs and paths makes it work.

I've been trying to upgrade to a newer version of the nodejs rules, and have been unable to because I can't make "rootDirs" work. I've been using "paths" which has worked just fine until the more recent versions:

zemn-me/monorepo@8e4de45

Edit: I've managed to get it to work, and these were my findings:

  1. rootDirs does not on its own allow absolute imports. Instead, rootDirs allows many directories to be virtually merged into a single file tree. This has no effect on absolute imports.
  2. It is baseurl which typically allows non-relative imports. However, the execution location of tsc appears to be the directory above bazel-out, which is why one less ../ is needed than expected. Setting baseurl to e.g. "bazel-out/k8-fastbuild/bin" will make your code build if all your code is in that directory.
  3. Baseurl alone cannot allow absolute imports under bazel! This is because even though 'rootDirs' merges the paths into one big virtual dir, the absolute paths are still resolved relative to 'baseUrl'. Paths should map "" to "./" as well as every 'rootDir', e.g. 'bazel-out/k8-fastbuild/bin/*'

For me, with my tsconfig.json at root, this was the minimum set of working options:

{
	"$schema": "https://json.schemastore.org/tsconfig",
	"compilerOptions": {
		"baseUrl": "./",
		"rootDirs": [
			"bazel-out/k8-fastbuild/bin"
		],
		"paths": {
			"*": [
				"./*",
				"bazel-out/k8-fastbuild/bin/*"
			]
		}
	},

This issue has been automatically marked as stale because it has not had any activity for 6 months. It will be closed if no further activity occurs in 30 days. Collaborators can add a "cleanup" or "need: discussion" label to keep it open indefinitely. Thanks for your contributions to rules_nodejs!

I switched to rules_js, which doesn't have this issue.