nx: 'rootDir' is expected to contain all source files. Bundle failed: test-icons
Current Behavior
Now when I run build command in our repo with multiple publishable libs, I get error like this:
test-icons:build-lib
Bundling test-icons...
Error during bundle: Error: /Users/stupic/Documents/demos/build-lib-bug-repro/libs/test-icons/src/index.ts(2,15): semantic error TS6059: File '/Users/stupic/Documents/demos/build-lib-bug-repro/libs/test-core/src/index.ts' is not under 'rootDir' '/Users/stupic/Documents/demos/build-lib-bug-repro/libs/test-icons/src'. 'rootDir' is expected to contain all source files.
Bundle failed: test-icons
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
> NX Ran target build-lib for project test-icons (3s)
✖ 1/1 failed
✔ 0/1 succeeded [0 read from cache]
Expected Behavior
Expect to build successfully or with a better error message like: test-core has no build-lib target.
Steps to Reproduce
- clone the repro repo:
git clone git@github.com:SunStupic/build-lib-bug-repro.git
pnpm inx run test-icons:build-lib
Failure Logs
test-icons:build-lib
Bundling test-icons...
Error during bundle: Error: /Users/stupic/Documents/demos/build-lib-bug-repro/libs/test-icons/src/index.ts(2,15): semantic error TS6059: File '/Users/stupic/Documents/demos/build-lib-bug-repro/libs/test-core/src/index.ts' is not under 'rootDir' '/Users/stupic/Documents/demos/build-lib-bug-repro/libs/test-icons/src'. 'rootDir' is expected to contain all source files.
Bundle failed: test-icons
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
> NX Ran target build-lib for project test-icons (3s)
✖ 1/1 failed
✔ 0/1 succeeded [0 read from cache]
Environment
nx report
> NX Running global Nx CLI with PNPM may have issues.
Prefer to use "pnpm" (https://pnpm.io/cli/exec) to execute commands in this workspace.
TIP create a shortcut such as: alias pnx="pnpm nx --"
> NX Report complete - copy this into the issue template
Node : 16.15.1
OS : darwin x64
pnpm : 7.5.0
nx : 14.4.3
@nrwl/angular : Not Found
@nrwl/cypress : 14.4.3
@nrwl/detox : Not Found
@nrwl/devkit : Not Found
@nrwl/eslint-plugin-nx : 14.4.3
@nrwl/express : Not Found
@nrwl/jest : 14.4.3
@nrwl/js : Not Found
@nrwl/linter : 14.4.3
@nrwl/nest : Not Found
@nrwl/next : Not Found
@nrwl/node : Not Found
@nrwl/nx-cloud : Not Found
@nrwl/nx-plugin : Not Found
@nrwl/react : 14.4.3
@nrwl/react-native : Not Found
@nrwl/schematics : Not Found
@nrwl/storybook : Not Found
@nrwl/web : 14.4.3
@nrwl/workspace : 14.4.3
typescript : 4.7.4
---------------------------------------
Community plugins:
Workaround
Now the workaround is simple, we need to add build-lib for all the publishable packages or we change back to use build.
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 1
- Comments: 22 (3 by maintainers)
Commits related to this issue
- fix(rollup): use workspace rootDir while compiling TS files fix: #11289 — committed to kopach/nx by kopach 8 months ago
- fix(rollup): use workspace rootDir while compiling TS files fix: #11289 — committed to kopach/nx by kopach 8 months ago
- fix(rollup): use workspace rootDir while compiling TS files fix: #11289 — committed to kopach/nx by kopach 8 months ago
- fix(bundling): use workspace rootDir while compiling TS files fix: #11289 — committed to kopach/nx by kopach 8 months ago
- fix(bundling): use workspace rootDir while compiling TS files fix: #11289 — committed to kopach/nx by kopach 8 months ago
- fix(bundling): use workspace rootDir while compiling TS files fix: #11289 — committed to kopach/nx by kopach 8 months ago
To help everyone understand what’s going on, here is the process of how I found the root cause.
What’s the problem
Say we have a monorepo, with several libraries inside, let’s name them
lib-a,lib-bandlib-c.lib-adepends onlib-bandlib-c, in/path-to-monorepo/libs/lib-a/src/foo.tsx, there will be:Path aliases are defined in root
tsconfig.base.json(which is extended by roottsconfig.json):@project-org/lib-bpoints to/path-to-monorepo/libs/lib-b/src/bar.ts@project-org/lib-cpoints to/path-to-monorepo/libs/lib-c/src/tor.tslib-ahas a build targetbuild-lib, which invokes executor@nrwl/web:rollup, another build targetbuildwhich invokesbuild-liband some other targets.lib-bhas only a build targetbuildwhich also invokes executor@nrwl/web:rollup,lib-chas 2 build targetsbuildandbuild-libjust likelib-a.Here is the essential part of
project.jsonoflib-a:And here is the essential part of
project.jsonoflib-b:And here is the essential part of
project.jsonoflib-c:All
tsconfig.lib.jsonextends the roottsconfig.base.json.Now when we issue
nx run lib-a:build, we’ll see an error like:What’s strange is, there’s NO such error for
lib-b.Dig into the source code of nx to find the root cause
We can add
--verboseoption when buildinglib-ato see where exactly the error is thrown, and it takes us here, hmm, doesn’t help too much.Let’s dive directly into rollup executor then.
NOTE the original error says
TS6059- which means it is thrown bytsc. Although the library is transpiled by babel by default,tscmust be invoked somewhere.Ah, here it is. But, hmm, still doesn’t know what could go wrong.
Let’s take a look what
createCompilerOptions(options, dependencies)produces.But hold on,
optionsis rollup options, what aboutdependencies? It’s the calculated project dependencies, which looks like:However we’ll find
@project-org/lib-bmissing in the list. Stay calm, we’ll come back to this later.With this list of dependencies,
createCompilerOptions(options, dependencies)produces:Huh?
@project/lib-cpoints todist/libs/lib-cinstead oflibs/lib-c/src/tor.ts, why?In
packages/workspace/src/utilities/buildable-libs-utils.ts,computeCompilerOptionsPaths()reads path aliases defined in project’stsconfig.jsonand update them, inupdatePaths(),paths[dep.name] = dep.outputs. Ah ha, this is where the outputs folderdist/libs/lib-cis used to replaced the original path. And because@project-org/lib-bis missing in the dependency list, its path alias stays intact.What’s inside
dist/libs/lib-c? Generated.d.tsfiles, transpiled.jsfiles, etc., anyway NO.tssource files, thus won’t break TS check performed byrollup-plugin-typescript2.However,
@project/lib-bis not so lucky,libs/lib-b/src/foo.tsis a TS source file itself outside ofrootDir, thustscwill complain.Now, the question becomes, why is
@project-org/lib-bmissing in the dependency list?Let’s get back to
const { target, dependencies } = calculateProjectDependencies(...), one of the arguments of this function call,projectGraph, is read fromnode_modules/.cache/nx/nxdeps.json(default path).And next is the essential part.
const depNode = projGraph.nodes[dep] || projGraph.externalNodes[dep];, whereprojGraph.nodeslooks like:if (isBuildable(targetName, depNode)),targetNameisbuild-libsince rollup executor is invoked bybuild-liboflib-a.Let’s look at the definition of
isBuildable(), it determines whether a dependency is buildable by:As for
lib-c, it returnstrue. But as forlib-b, since it doesn’t have abuild-libtarget, that condition returnsfalse! This is whylib-bwas missing in the dependency list.Solution
To make nx thinks
lib-bas buildable, we need to define abuild-libtarget for it. Here is the updated version ofproject.jsonoflib-b:To summarize it, all internal dependencies of a library must have a build target of the same name, in order to make nx treat them as buildable.
Other workarounds
rollup-plugin-typescript2.@project-org/lib-bintsconfig.base.jsonto"@project-org/lib-b": ["dist/libs/lib-b", "libs/lib-b/src/bar.ts"]@project-org/lib-bwill point todistdirectory which contains.d.tsfiles but not real source.tsfiles, not a good development experience."@project-org/lib-b": ["dist/libs/lib-b"]inlibs/lib-b/tsconfig.lib.json@project-org/lib-bstill points tolibs/lib-b/src/bar.tsin our editor (because of the path alias"@project-org/lib-b": ["libs/lib-b/src/bar.ts"]in roottsconfig.json), while"@project-org/lib-b": ["dist/libs/lib-b"]inlibs/lib-b/tsconfig.lib.jsonoverrides it - whenparsedTSConfig.compilerOptions.pathsexists, path aliases inparsedTSConfig.extendsare bypassed.Any update on this? all workaround mentioned above didn’t work for me. I am using nx v14.3.6 with react library and tried also with latest nx version v15.2.1 as well, but the result is same.
Thats for sure works, but is hard to develop this way. You have to manually build libraries in correct order. You are also importing now from DIST, means changes you make are not seamless applied to the rest of the project.
@7alip Must have saved me hours with your comment. Thank you
The
'rootDir' is expected to contain all source fileserror can be caused for a number of reasons. Some might be legit TS setup issues leading to trying to compile files that are outside of the project root dir, while in a lot of cases, it’s down to how we handle “buildable” libraries in Nx incremental builds scenarios.As explained (great detective work! 👏🏻 ) by @athrunsun in https://github.com/nrwl/nx/issues/11289#issuecomment-1195616035, Nx executors that support the incremental builds scenarios, look for targets with the same name as the build target name of the top-level project being built. The found targets’ info will be used to collect their output paths and remap on the fly the TS path mappings existing in the tsconfig file at the root of your workspace to point to the compiled source. The remapping is done so we can provide the best possible DX. By default, your projects point to the dependency sources (that’s what your IDE will use) and at build time, it will point to the dependency compiled code to avoid building it again. When looking up for the dependencies targets, if they are not found, the TS path mapping will remain pointing to the source code of the dependency and given it’s a different project, its location will be outside of the
rootDirof the project that depends on it. Hence the error.Also, if the dependencies between targets are not correctly configured (using
targetDefaultsand/ordependsOn), the task graph won’t be constructed correctly, and therefore, the targets from dependencies won’t be found leading to the same issue.Please note that error will also happen if the dependencies of buildable libraries are not buildable (have a target to build the library). In such cases, no target will be found because there’s none and the same error will be thrown. Buildable libraries must depend on other buildable libraries. There are a couple of executors that support inlining non-buildable libraries into buildable libraries, but that feature is highly experimental and it’s not recommended.
Identifying the buildable target from the dependencies has always been the challenge and we’ve had a constraint of keeping the target names aligned. Nx generators always generate “build” target, but of course, in real-world scenarios, developers can change those names and use something else. This is often the case when needing to do extra tasks and new targets are added and composed to build a project.
In Nx 16.6.0, we introduced a new way to identify the build target of dependent buildable libraries. The new way doesn’t rely on the targets having the same name, but rather on the information available in the task graph. It’s still key to have the target dependencies correctly configured. This behavior is not yet enabled by default, but you can try it by setting the following env var:
NX_BUILDABLE_LIBRARIES_TASK_GRAPH=true.We’re trying to get feedback whether this new way works as expected before turning it on by default. Could you try it and let us know how it goes? We want to know:
If you already solved your issue by ensuring the same target name, you could still try this and provide feedback. As mentioned above, we want to make sure the new way doesn’t break existing scenarios.
If it doesn’t work for you, please try to provide a reproduction so the feedback is actionable and we can troubleshoot it.
In my case, I noticed that when I moved some files to a different folder, some relative import paths were automatically changed.
It was
import { } from 'libs/types/src...'but should beimport { } from '../common'Changing the tsconfig paths helped compiling the project, but it raises another error `Error: Cannot find module ‘@my-org/lib-b’, because the imported lib path is not changed in the compiled file