try to understand an error report of npm and fail to find the problem - surprisingly the deletion of the node_modules directory fixed it. We were in the process to update angular to 18+ and nx to 19+.
Found: @angular-devkit/[email protected]
node_modules/@angular-devkit/build-angular
dev @angular-devkit/build-angular@"18.0.4" from the root project
peer @angular-devkit/build-angular@">= 15.0.0 < 18.0.0" from @nx/[email protected]
node_modules/@nx/angular
@nx/angular@"19.3.0" from the root project
@nx/angular@"18.3.4" from @nrwl/[email protected]
node_modules/@nrwl/angular
@nrwl/angular@"18.3.4" from @nx/[email protected]
peer @angular-devkit/build-angular@">=15.0.0 <18.0.0" from [email protected]
node_modules/jest-preset-angular
dev jest-preset-angular@"14.1.1" from the root project
Could not resolve dependency:
dev @angular-devkit/build-angular@"18.0.4" from the root project
Conflicting peer dependency: @angular/[email protected]
node_modules/@angular/compiler-cli
peer @angular/compiler-cli@"^18.0.0" from @angular-devkit/[email protected]
node_modules/@angular-devkit/build-angular
dev @angular-devkit/build-angular@"18.0.4" from the root project
How i understand the last part:
Why does it fail to resolve @angular/[email protected] when its clearly a valid version ?
How i understand the first part:
Why does npm use the old version of jest-preset-angular and nx/angular for resolving ? it seems like it ignore versions specified in the package.json and use the current installed.
(deleting nod_modules to fix an npm dependency problem seem like a bug in npm itself to me)
package.json
"dependencies": {
"@abp/ng.components": "8.1.3",
"@abp/ng.core": "8.1.3",
"@abp/ng.oauth": "8.1.3",
"@abp/ng.theme.shared": "8.1.3",
"@angular/animations": "18.0.3",
"@angular/common": "18.0.3",
"@angular/compiler": "18.0.3",
"@angular/core": "18.0.3",
"@angular/forms": "18.0.3",
"@angular/localize": "18.0.3",
"@angular/platform-browser": "18.0.3",
"@angular/platform-browser-dynamic": "18.0.3",
"@angular/router": "18.0.3",
"@ngrx/effects": "18.0.0",
"@ngrx/store": "18.0.0",
"@ngrx/operators": "18.0.0",
"@nx/angular": "19.3.0",
"@puschie286/golden-layout": "^2.6.2",
"@types/lodash-es": "^4.17.12",
"angular-oauth2-oidc": "^17.0.2",
"bootstrap-icons": "^1.11.3",
"lodash-es": "^4.17.21",
"primeicons": "^7.0.0",
"primeng": "^17.18.1",
"primeng-locale": "github:primefaces/primelocale",
"primeng-sass-theme": "github:primefaces/primeng-sass-theme",
"rxjs": "~7.8.1",
"ts-debounce": "^4.0.0",
"tslib": "^2.6.2",
"zone.js": "0.14.4"
},
"devDependencies": {
"@abp/ng.schematics": "^8.1.3",
"@abp/nx.generators": "^8.1.3",
"@angular-devkit/build-angular": "18.0.4",
"@angular-devkit/core": "18.0.4",
"@angular-devkit/schematics": "18.0.4",
"@angular-eslint/eslint-plugin": "18.0.1",
"@angular-eslint/eslint-plugin-template": "18.0.1",
"@angular-eslint/template-parser": "18.0.1",
"@angular/cli": "~18.0.0",
"@angular/compiler-cli": "18.0.3",
"@angular/language-service": "18.0.3",
"@ngrx/eslint-plugin": "18.0.0",
"@ngrx/schematics": "18.0.0",
"@ngrx/store-devtools": "18.0.0",
"@nx-dotnet/core": "^2.2.0",
"@nx/cypress": "19.3.0",
"@nx/eslint": "19.3.0",
"@nx/eslint-plugin": "19.3.0",
"@nx/jest": "19.3.0",
"@nx/js": "19.3.0",
"@nx/plugin": "19.3.0",
"@nx/web": "19.3.0",
"@nx/workspace": "19.3.0",
"@schematics/angular": "18.0.4",
"@swc-node/register": "1.9.2",
"@swc/core": "1.5.7",
"@types/jest": "^29.5.12",
"@types/node": "^20.11.17",
"@typescript-eslint/eslint-plugin": "7.3.0",
"@typescript-eslint/parser": "7.3.0",
"@typescript-eslint/utils": "^8.0.0-alpha.28",
"autoprefixer": "^10.4.17",
"cypress": "13.8.1",
"daisyui": "^4.6.3",
"eslint": "8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-cypress": "^2.15.1",
"jasmine-marbles": "~0.9.2",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-preset-angular": "14.1.1",
"jsonc-eslint-parser": "^2.4.0",
"nx": "19.3.0",
"postcss": "^8.4.38",
"prettier": "^3.2.5",
"tailwindcss": "^3.4.3",
"ts-jest": "^29.1.2",
"ts-node": "10.9.2",
"typescript": "5.4.3"
}
@nx/[email protected]
and [email protected]
both specify that they need a @angular-devkit/build-angular
that is >= 15.0.0 < 18.0.0
.
Unfortunately, this range does not include any version of 18.x.x
. The latest version matching that range is 17.3.8
according to the NPM semver calculator.
For @nx/angular
it looks like this was fixed in https://github.com/nrwl/nx/pull/22509. For jest-preset-angular
it was fixed in https://github.com/thymikee/jest-preset-angular/blob/main/CHANGELOG.md#1410-2024-05-21.
It uses the old versions because you likely have a package-lock.json
which is storing the transitive versions of these dependencies from a previous install. This is by design and best practice -- but it requires some extra work to manage in complex upgrade scenarios. Please see package-lock.json.
With the latest NPM, you need to do something like npm update --save @nx/angular jest-preset-angular
.
And ensure the resulting changes to the package-lock.json
and (possibly, this will only change if they were direct deps) package.json
are committed. Make sure in CI that it fails the build if someone commits a change that should have caused a package-lock.json
update, but it was not included. Practically that means in CI you use npm ci
and never npm install
.
And of course, never commit node_modules
.