I'm not able to run the 'build' command on an Angular app inside a NX workspace anymore. An error occurs while NX is building a dependent library that accesses 'localStorage' on the dom:
Executing task: npx nx run my-app:build --configuration=production
× 1/20 dependent project tasks failed (see below)
√ 19/20 dependent project tasks succeeded [19 read from cache]
libs\my-lib\src\example-file.ts:43:5 error TS2304: Cannot find name 'localStorage'.
When I build the library that causes the issue alone (Without the Angular App), i don't get any error:
Executing task: npx nx run my-lib:build
√ 8/8 dependent project tasks succeeded [8 read from cache]
NX Successfully ran target build for project my-lib and 8 tasks it depends on (1s)
The issue occurs both with 'production' and 'development' builds.
The issue only occurs with the 'build' command, everything works well with the 'serve' command.
I tried adding "lib": ["es2022", "dom"] on tsconfig.json and tsconfig.app.json of the app to allow access to the DOM. It doesn't solve the issue.
If I add "lib": ["es2022"] (without DOM) on tsconfig.lib.json of the library and build the library alone, the error occurs.
I tried adding "ssr": false and "prerender": false to project.json file of the angular app, as I have seen that some people get the issue while trying to access localStorage on Server Side Rendering.
Any help would be greatly appreciated.
Angular version: 18.2.10
NX version: 20.0.7
Typescript version: 5.5.4
project.json of the angular app:
{
"name": "my-app",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "app",
"sourceRoot": "apps/my-app/src",
"tags": [],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"verbose": true,
"outputPath": "dist/apps/my-app",
"index": "apps/my-app/src/index.html",
"browser": "apps/my-app/src/main.ts",
"polyfills": [],
"tsConfig": "apps/my-app/tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
"apps/my-app/src/favicon.ico",
"apps/my-app/src/assets"
],
"styles": [
"apps/my-app/src/styles.scss",
{
"input": "apps/my-app/src/assets/styles/themes/dark-cyan-theme.scss",
"bundleName": "dark-cyan-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/dark-deep-purple-theme.scss",
"bundleName": "dark-deep-purple-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/dark-grey-theme.scss",
"bundleName": "dark-grey-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/dark-light-green-theme.scss",
"bundleName": "dark-light-green-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/dark-pink-theme.scss",
"bundleName": "dark-pink-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/dark-yellow-theme.scss",
"bundleName": "dark-yellow-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/light-amber-theme.scss",
"bundleName": "light-amber-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/light-blue-gray-theme.scss",
"bundleName": "light-blue-gray-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/light-blue-theme.scss",
"bundleName": "light-blue-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/light-indigo-theme.scss",
"bundleName": "light-indigo-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/light-pink-theme.scss",
"bundleName": "light-pink-theme",
"inject": false
},
{
"input": "apps/my-app/src/assets/styles/themes/light-teal-theme.scss",
"bundleName": "light-teal-theme",
"inject": false
}
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "2mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all",
"ssr": false,
"prerender": false
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true,
"ssr": false,
"prerender": false
}
},
"defaultConfiguration": "production"
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "my-app:build:production"
},
"development": {
"buildTarget": "my-app:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "my-app:build"
}
},
"lint": {
"executor": "@nx/eslint:lint"
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/my-app/jest.config.ts"
}
}
}
}
I got a working solution, I replaced :
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:application",
...
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
...
},
},
with:
"targets": {
"build": {
"executor": "@nx/angular:application",
...
},
"serve": {
"executor": "@nx/angular:dev-server",
...
},
},
in the project.json of the angular app