Upgrading from Nx 7.3 to 7.4 would not change nx affected:build --all build sequence
Nx 7.4 (also tested with 7.5.1) changed the build sequence for nx affected:build --all and seems not taking in account workspace library dependencies. Angular build fails with error "The [lib-dependecy-element] could not be found". If I build the missing dependency using ng build , nx affected:build --all works just fine.
I'll try to create a simple environment to reproduce this, but wonder if there was some major change in dependency resolution from 7.3 to 7.4.
Please provide any relevant information about your setup:
"@angular-devkit/build-angular": "~0.10.0",
"@angular-devkit/build-ng-packagr": "~0.10.0",
"@angular/cli": "~7.1.0",
Sorry for the late reply. Could you provide a repro?
Hi @vsavkin I can provide a repro on this:
https://github.com/tanepiper/ngx-tinynodes/tree/release/v1.2.0
I moved my plugin architecture to be a separate module that is included in the monorepo. It's already published to NPM, but when I try build my main library it fails:
โ ngx-tinynodes git:(release/v1.2.0) โ ng build ngx-editorjs
Building Angular Package
Building entry point '@tinynodes/ngx-editorjs'
Compiling TypeScript sources through ngc
Bundling to FESM2015
BUILD ERROR
Could not resolve entry (/Users/tane/work/personal/ngx-tinynodes/dist/libs/ngx-editorjs/esm2015/tinynodes-ngx-editorjs.js)
Error: Could not resolve entry (/Users/tane/work/personal/ngx-tinynodes/dist/libs/ngx-editorjs/esm2015/tinynodes-ngx-editorjs.js)
at error (/Users/tane/work/personal/ngx-tinynodes/node_modules/rollup/dist/rollup.js:3460:30)
at /Users/tane/work/personal/ngx-tinynodes/node_modules/rollup/dist/rollup.js:21474:17
at async Promise.all (index 0)
Could not resolve entry (/Users/tane/work/personal/ngx-tinynodes/dist/libs/ngx-editorjs/esm2015/tinynodes-ngx-editorjs.js)
Error: Could not resolve entry (/Users/tane/work/personal/ngx-tinynodes/dist/libs/ngx-editorjs/esm2015/tinynodes-ngx-editorjs.js)
at error (/Users/tane/work/personal/ngx-tinynodes/node_modules/rollup/dist/rollup.js:3460:30)
at /Users/tane/work/personal/ngx-tinynodes/node_modules/rollup/dist/rollup.js:21474:17
at async Promise.all (index 0)
As you can see from the below screenshot through it the folder structure is different, it also builds the local dep and that results in another folder level.

Hopefully this can help you track down the bug as it seems to be affecting a few people.
I just solved the dependency resolution by changing the projects declaration order on angular.json. Is that supposed to be the solution? Or is your intent that Nx solves inter-libraries dependencies by itself @vsavkin?
@igortg the order of declarations in angular.json should not matter. It's probably a bug. Could you provide a minimal repro demonstrating the issue?
@tanepiper Hey! The provided link doesn't work. When I clone master and run ngx-editorjs, it builds successfully.
@vsavkin I ran into a similar issue. I have an Nx monorepo with no applications and with two published libraries, library-a and library-b. I added a third library, internal-lib, that I don't want to publish. library-b depends on internal-lib.
My build output is the following:
Running build for projects:
library-b
Building Angular Package
Building entry point '@my-company/library-b'
Compiling TypeScript sources through ngc
Bundling to FESM2015
BUILD ERROR
Could not resolve entry (/Users/me/src/my-repo/dist/libs/library-b/esm2015/my-company-library-b.js)
Error: Could not resolve entry (/Users/me/src/my-repo/dist/libs/library-b/esm2015/my-company-library-b.js)
at error (/Users/me/src/my-repo/node_modules/rollup/dist/rollup.js:3460:30)
at /Users/me/src/my-repo/node_modules/rollup/dist/rollup.js:21474:17
Could not resolve entry (/Users/me/src/my-repo/dist/libs/library-b/esm2015/my-company-library-b.js)
Error: Could not resolve entry (/Users/me/src/my-repo/dist/libs/library-b/esm2015/my-company-library-b.js)
at error (/Users/me/src/my-repo/node_modules/rollup/dist/rollup.js:3460:30)
at /Users/me/src/my-repo/node_modules/rollup/dist/rollup.js:21474:17
I think this is an issue with paths. The `dist` folder for `library-a`, which does not depend on `internal-lib`, is the following:
tree dist/libs/library-adist/libs/library-a โโโ README.md โโโ bundles โย ย โโโ my-company-library-a.umd.js โย ย โโโ my-company-library-a.umd.js.map โย ย โโโ my-company-library-a.umd.min.js โย ย โโโ my-company-library-a.umd.min.js.map โโโ esm2015 โย ย โโโ index.js โย ย โโโ index.ngsummary.json โย ย โโโ lib โย ย โย ย โโโ library-a.js โย ย โย ย โโโ library-a.ngsummary.json โย ย โโโ my-company-library-a.js โย ย โโโ my-company-library-a.ngsummary.json โโโ esm5 โย ย โโโ index.js โย ย โโโ lib โย ย โย ย โโโ library-a.js โย ย โโโ my-company-library-a.js โโโ fesm2015 โย ย โโโ my-company-library-a.js โย ย โโโ my-company-library-a.js.map โโโ fesm5 โย ย โโโ my-company-library-a.js โย ย โโโ my-company-library-a.js.map โโโ index.d.ts โโโ lib โย ย โโโ library-a.d.ts โโโ package.json โโโ my-company-library-a.d.ts โโโ my-company-library-a.metadata.json
But for library-b, which depends on internal-lib, the directory structure is different:
tree dist/libs/library-b
dist/libs/library-b
โโโ esm2015
โย ย โโโ internal-lib
โย ย โย ย โโโ src
โย ย โย ย โโโ if-true.js
โย ย โย ย โโโ index.js
โย ย โย ย โโโ unless.js
โย ย โโโ library-b
โย ย โโโ src
โย ย โโโ index.js
โย ย โโโ index.ngsummary.json
โย ย โโโ my-company-library-b.js
โย ย โโโ my-company-library-b.ngsummary.json
โย ย โโโ library-b.js
โย ย โโโ library-b.ngsummary.json
โโโ esm5
โย ย โโโ internal-lib
โย ย โย ย โโโ src
โย ย โย ย โโโ if-true.js
โย ย โย ย โโโ index.js
โย ย โย ย โโโ unless.js
โย ย โโโ library-b
โย ย โโโ src
โย ย โโโ index.js
โย ย โโโ my-company-library-b.js
โย ย โโโ library-b.js
โโโ internal-lib
โย ย โโโ src
โย ย โโโ if-true.d.ts
โย ย โโโ index.d.ts
โย ย โโโ unless.d.ts
โโโ library-b
โโโ src
โโโ index.d.ts
โโโ my-company-library-b.d.ts
โโโ my-company-library-b.metadata.json
โโโ library-b.d.ts
Please let me know if I can provide any more information. If you feel you need a minimal reproduction to debug further, I can try to create one.
edit: this may be related to #930.
@tanepiper Hey! The provided link doesn't work. When I clone master and run
ngx-editorjs, it builds successfully.
Hi there @vsavkin yes it does now as I don't ship the core with any plugins now using the plugin module as a hard dependency, it's now a peer dependency.
If you look at the commit here: https://github.com/tanepiper/ngx-tinynodes/commit/14d0cc3a9eb0c2c7f65a4431ac2da7d3f4ec06d4
Clone from this commit and you should see the issue.
@vsavkin @AdamVig I can confirm that #930 does seem to fix it, specifically, https://github.com/nrwl/nx/issues/930#issuecomment-480810046, where adding the dist path in the tsconfig worked.
Here's a simple repository to reproduce the issue:
https://github.com/luchsamapparat/nx-lib-dependency-poc
just run npm install and then ng build --project library-b
You can reproduce this issue by following these steps:
create-nx-workspace nx-lib-dependency-pocng g lib library-a --publishableng g lib library-b --publishable./libs/library-b/src/lib/library-b.module.tsng g app demo)ng build --project library-bBuilding Angular Package
Building entry point '@poc/library-b'
Compiling TypeScript sources through ngc
Bundling to FESM2015
BUILD ERROR
Could not resolve entry ([...]\nx-lib-dependency-poc\dist\libs\library-b\esm2015\poc-library-b.js)
Error: Could not resolve entry ([...]\nx-lib-dependency-poc\dist\libs\library-b\esm2015\poc-library-b.js)
at error ([...]\nx-lib-dependency-poc\node_modules\rollup\dist\rollup.js:3460:30)
at [...]\nx-lib-dependency-poc\node_modules\rollup\dist\rollup.js:21474:17
Could not resolve entry ([...]\nx-lib-dependency-poc\dist\libs\library-b\esm2015\poc-library-b.js)
Error: Could not resolve entry ([...]\nx-lib-dependency-poc\dist\libs\library-b\esm2015\poc-library-b.js)
at error ([...]\nx-lib-dependency-poc\node_modules\rollup\dist\rollup.js:3460:30)
at [...]\nx-lib-dependency-poc\node_modules\rollup\dist\rollup.js:21474:17
When I do the same with a vanilla Angular workspace, this issue does not occur. As @tanepiper suggests, this is probably related to the path mapping in the tsconfig file.
Right, I think the simplest thing to make it work is to add the following:
"paths": {
"@issue1077/library-a": [
"dist/libs/library-a",
"libs/library-a/src/index.ts"
],
"@issue1077/library-b": [
"dist/libs/library-b",
"libs/library-b/src/index.ts"
]
}
affected:* command topologically sorts all the projects, so it will always build library-a before library-b.
@vsavkin The workaround you shared above does not work with the --parallel flag, for example nx affected:build --parallel.
It seems like it would be relatively straightforward (and relevant to the core offering of Nx) to make nx affected:* --parallel aware of the dependency graph, not building a project until all of that project's dependencies are built.
It would be nice to have a command like nx build <project>, too, that builds all of the project's dependencies before building the project itself.
Hey folks.
We did a lot of work on building multiple libraries depending on each other.
affected:build will finally sort the projects and run what it can in parallel. This finally works reliably. node_modules. package.json to resolve the library cause that's what you would use if the library was published to NPM.Since so much has been improved, I'm going to close this issues. If you use Nx 8.12.7 or 9.0.2 and you have issues with buildable/publishable libraries, please open an issue, and we will take a look asap. This use case is very important for us.
@vsavkin Thanks for the update! I have been eagerly awaiting this. My current workaround in continuous integration has been the following:
affected="$(npx nx print-affected --with-deps)"
echo 'affected:' "$affected"
# Extract `projects` field and output in space-delimited format
projects="$(echo "$affected" | jq --raw-output '.projects | join(" ")')"
echo 'projects:' "$projects"
for project in $projects; do
npx ng build --prod "$project"
done
As you can see, the projects are built serially, which is slow. I did always find it curious that the `print-affected` command printed the projects in the correct order but the `affected:build` command did not.
In local development, our "workaround" is to run the build three or four times (once for each level of our dependency tree) to get everything built.
I wanted to share the above in case it helps others!
---
I updated to Nx 9.0.2 (see report below) and ran `npx nx affected:build`.
nx report@nrwl/angular : 9.0.2 @nrwl/cli : 9.0.2 @nrwl/cypress : 9.0.2 @nrwl/eslint-plugin-nx : 9.0.2 @nrwl/express : Not Found @nrwl/jest : 9.0.2 @nrwl/linter : 9.0.2 @nrwl/nest : Not Found @nrwl/next : Not Found @nrwl/node : Not Found @nrwl/react : 9.0.2 @nrwl/schematics : Not Found @nrwl/tao : 9.0.2 @nrwl/web : 9.0.2 @nrwl/workspace : 9.0.2 typescript : 3.7.5
Since I had changed many dependencies in package.json, the command attempted to build every project. Unfortunately, it _still_ did not build them in the correct order. It built one "base" project (many things depend on it, but it depends on nothing) first, but did not built the other "base" project until second-to-last.
I am happy to share my dependency graph and build output privately, if that would be helpful.
Most helpful comment
Hey folks.
We did a lot of work on building multiple libraries depending on each other.
affected:buildwill finally sort the projects and run what it can in parallel. This finally works reliably.node_modules.package.jsonto resolve the library cause that's what you would use if the library was published to NPM.Since so much has been improved, I'm going to close this issues. If you use Nx 8.12.7 or 9.0.2 and you have issues with buildable/publishable libraries, please open an issue, and we will take a look asap. This use case is very important for us.