angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.74k stars 11.98k forks source link

Angular16 esbuild extremely slow #25479

Closed LorinRenodeyn closed 11 months ago

LorinRenodeyn commented 1 year ago

Command

build, serve

Is this a regression?

The previous version in which this bug was not present was

No response

Description

Wit the advent of Angular 16 I figured I'd give the esbuild builder another try after it not providing much benefit for my project with Angular 15 and initially not working with angular-material back then.

Fully on v16, the esbuild does run. However, instead of faster it is extremely slow compared to the default builder.

I'm talking 658s for ng-serve --proxy-config proxy.config.json vs 119831ms with the default builder

image

And 694s for ng build -c=production --subresource-integrity vs 149683ms with the default builder

image

At the moment, I'm in the dark as to what could be causing this issue. The only possible hunch would be the iban commonjs module?

Minimal Reproduction

The only things I have changed were in the configuration: adding the -esbuild suffix to the specified builder and importing the material icons font via the styles array instead of via an scss file.

Package JSON:

{
  "name": "esl-apor-portalweb",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "start:proxy": "ng serve --proxy-config proxy.config.json",
    "build": "ng build",
    "build:prod": "ng build -c=production --subresource-integrity",
    "watch": "ng build --watch --configuration development",
    "test": "jest --runInBand",
    "test:watch": "jest --watch --changedSince master",
    "test:local": "jest --coverage",
    "test:changed": "jest --coverage --changedSince master",
    "docs:json": "compodoc -p ./tsconfig.json -e json -d .",
    "storybook": "ng run esl-apor-portalweb:storybook",
    "build-storybook": "ng run esl-apor-portalweb:build-storybook",
    "prepare": "husky install",
    "lint": "ng lint --cache",
    "generate:version": "echo 'todo'"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^16.1.3",
    "@angular/cdk": "16.1.3",
    "@angular/common": "^16.1.3",
    "@angular/compiler": "^16.1.3",
    "@angular/core": "^16.1.3",
    "@angular/forms": "^16.1.3",
    "@angular/material": "16.1.3",
    "@angular/material-luxon-adapter": "^16.1.3",
    "@angular/platform-browser": "^16.1.3",
    "@angular/platform-browser-dynamic": "^16.1.3",
    "@angular/router": "^16.1.3",
    "@ngx-translate/core": "^15.0.0",
    "@ngx-translate/http-loader": "^8.0.0",
    "esl-apor-portalapi-v1-api": "^1.3.0",
    "iban": "^0.0.14",
    "luxon": "^3.3.0",
    "material-icons": "^1.13.8",
    "rxjs": "~7.8.1",
    "tslib": "^2.6.0",
    "zone.js": "~0.13.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^16.1.2",
    "@angular-eslint/builder": "16.0.3",
    "@angular-eslint/eslint-plugin": "16.0.3",
    "@angular-eslint/eslint-plugin-template": "16.0.3",
    "@angular-eslint/schematics": "16.0.3",
    "@angular-eslint/template-parser": "16.0.3",
    "@angular/cli": "~16.1.2",
    "@angular/compiler-cli": "^16.1.3",
    "@chiragrupani/karma-chromium-edge-launcher": "^2.3.1",
    "@compodoc/compodoc": "^1.1.21",
    "@storybook/addon-essentials": "^7.0.24",
    "@storybook/addon-interactions": "^7.0.24",
    "@storybook/addon-links": "^7.0.24",
    "@storybook/angular": "^7.0.24",
    "@storybook/preset-scss": "^1.0.3",
    "@storybook/testing-library": "^0.2.0",
    "@types/iban": "^0.0.32",
    "@types/jest": "^29.5.2",
    "@types/luxon": "^3.3.0",
    "@types/node": "^20.3.2",
    "@typescript-eslint/eslint-plugin": "^5.60.1",
    "@typescript-eslint/parser": "^5.60.1",
    "css-loader": "^6.8.1",
    "eslint": "^8.43.0",
    "eslint-plugin-rxjs": "^5.0.3",
    "eslint-plugin-rxjs-angular": "^2.0.1",
    "eslint-plugin-storybook": "^0.6.12",
    "husky": "^8.0.3",
    "jest": "^29.5.0",
    "jest-preset-angular": "^13.1.1",
    "ngx-translate-testing": "^7.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "sass": "^1.63.6",
    "sass-loader": "^13.3.2",
    "storybook": "^7.0.24",
    "style-loader": "^3.3.3",
    "typescript": "~5.1.6"
  }
}

angular.json

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "cli": {
        "packageManager": "pnpm",
        "schematicCollections": ["@angular-eslint/schematics"],
        "analytics": false
    },
    "newProjectRoot": "projects",
    "projects": {
        "esl-apor-portalweb": {
            "projectType": "application",
            "schematics": {
                "@schematics/angular:component": {
                    "style": "scss",
                    "displayBlock": true
                }
            },
            "root": "",
            "sourceRoot": "src",
            "prefix": "cl",
            "architect": {
                "build": {
                    "builder": "@angular-devkit/build-angular:browser-esbuild",
                    "options": {
                        "outputPath": "dist/esl-apor-portalweb",
                        "index": "src/index.html",
                        "main": "src/main.ts",
                        "polyfills": "src/polyfills.ts",
                        "tsConfig": "tsconfig.app.json",
                        "inlineStyleLanguage": "scss",
                        "assets": ["src/favicon.ico", "src/assets"],
                        "styles": [
                            "src/googleFonts.scss",
                            "node_modules/material-icons/iconfont/material-icons.scss",
                            "src/styles.scss",
                            "src/theme.scss"
                        ],
                        "scripts": []
                    },
                    "configurations": {
                        "production": {
                            "budgets": [
                                {
                                    "type": "initial",
                                    "maximumWarning": "500kb",
                                    "maximumError": "1mb"
                                },
                                {
                                    "type": "anyComponentStyle",
                                    "maximumWarning": "2kb",
                                    "maximumError": "4kb"
                                }
                            ],
                            "fileReplacements": [
                                {
                                    "replace": "src/environments/environment.ts",
                                    "with": "src/environments/environment.prod.ts"
                                }
                            ],
                            "outputHashing": "all"
                        },
                        "development": {
                            "buildOptimizer": false,
                            "optimization": false,
                            "vendorChunk": true,
                            "extractLicenses": false,
                            "sourceMap": true,
                            "namedChunks": true
                        }
                    },
                    "defaultConfiguration": "production"
                },
                "serve": {
                    "builder": "@angular-devkit/build-angular:dev-server",
                    "configurations": {
                        "production": {
                            "browserTarget": "esl-apor-portalweb:build:production",
                            "headers": {
                                "Content-Security-Policy": "trusted-types angular angular#unsafe-bypass angular#bundler; require-trusted-types-for 'script';"
                            }
                        },
                        "development": {
                            "browserTarget": "esl-apor-portalweb:build:development",
                            "headers": {
                                "Content-Security-Policy": "trusted-types angular angular#unsafe-bypass angular#bundler; require-trusted-types-for 'script';"
                            }
                        }
                    },
                    "defaultConfiguration": "development"
                },
                "extract-i18n": {
                    "builder": "@angular-devkit/build-angular:extract-i18n",
                    "options": {
                        "browserTarget": "esl-apor-portalweb:build"
                    }
                },
                "lint": {
                    "builder": "@angular-eslint/builder:lint",
                    "options": {
                        "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
                    }
                },
                "storybook": {
                    "builder": "@storybook/angular:start-storybook",
                    "options": {
                        "browserTarget": "esl-apor-portalweb:build",
                        "port": 6006,
                        "compodoc": false,
                        "configDir": ".storybook"
                    }
                },
                "build-storybook": {
                    "builder": "@storybook/angular:build-storybook",
                    "options": {
                        "browserTarget": "esl-apor-portalweb:build",
                        "outputDir": "__storybook",
                        "quiet": true,
                        "compodoc": false
                    }
                }
            }
        }
    },
    "schematics": {
        "@angular-eslint/schematics:application": {
            "setParserOptionsProject": true
        },
        "@angular-eslint/schematics:library": {
            "setParserOptionsProject": true
        }
    }
}

Exception or Error

No response

Your Environment

Angular CLI: 16.1.2
Node: 18.12.1
Package Manager: pnpm 8.6.5
OS: win32 x64

Angular: 16.1.3
... animations, cdk, common, compiler, compiler-cli, core, forms
... material, material-luxon-adapter, platform-browser
... platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1601.2 (cli-only)
@angular-devkit/build-angular   16.1.2
@angular-devkit/core            16.1.2 (cli-only)
@angular-devkit/schematics      16.1.2 (cli-only)
@angular/cli                    16.1.2
@schematics/angular             16.1.2 (cli-only)
rxjs                            7.8.1
typescript                      5.1.6

Anything else relevant?

I am working on a Windows VDI via Citrix as mandated by the client, which is considerably slower than my own machine. However, the difference is nowhere near big enough to explan a 650+ second ng-serve command.

Package manager is PNPM

My app is split up in

Packages that may be relevant:

clydin commented 1 year ago

Can you try generating a new v16 project (ng new myapp --defaults) and provide the build times with the esbuild-based build system?

clydin commented 1 year ago

Also, I noticed that pnpm was being used. Is the Angular project also using Sass? Unfortunately, there is a module resolution limitation within the Sass compiler that can cause long resolution times when using either pnpm or yarn PnP. Can you also try using npm as the package manager to see if that has an effect?

LorinRenodeyn commented 1 year ago

Tried out switching from PNPM to regular NPM first, that shaved almost 600 seconds off the build time, resulting in 59s for ng serve and 70s for ng build. So that ends up in a ~50% improved compilation time if I can count correctly.

If the impact of the package manager is that dramatic, it should probably be mentioned in the guide and might be worth investigating if there is a possible way to mitigate this?

image
nicolae536 commented 1 year ago

I'm also facing a similar issue 🤔 not so dramatic but I just compared the previous webpack build for our app with the current esbuild from 16.1.1. Is this a know issue ? I mean the build time was never great and I hopped that it will be better with this change but going to a new tool which makes it slower is never desired 🤔 . Does anyone know why that might be ?

Build Time esbuild on my machine: Cold startup: 120s Rebuilds: 6-12s Build Time webpack on my machine: Cold startup: 102s Rebuilds: 3-6s

Machine specs:

Angular CLI: 16.1.3
Node: 16.18.1
Package Manager: npm 8.19.2
OS: darwin arm64

Angular: 16.1.3
... animations, cdk, cli, common, compiler, compiler-cli, core
... elements, forms, google-maps, language-service, material
... platform-browser, platform-browser-dynamic, platform-server
... router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1601.3
@angular-devkit/build-angular   16.1.3
@angular-devkit/core            16.1.3
@angular-devkit/schematics      16.1.3
@nguniversal/builders           16.1.1
@nguniversal/express-engine     16.1.1
@schematics/angular             16.1.3
rxjs                            7.5.7
typescript                      5.0.4
webpack                         5.86.0
elnipa commented 1 year ago

We're experiencing the same problem. We thought it would be only related to our project because there was nothing similar to find in the web. And we'd never thought that it would be related to pnpm.

Is there any hope that there will be a fix for this in a timely manner? Otherwise we would have to think about migrating away from pnpm.

harellevy commented 1 year ago

Same here. Angular 16 (with es-build and vite), storybook 7. For me it's 150s - 200s for bootstrap, 50s-60s for each change, about the same as if not worst than what I had before es-build / vite...

LorinRenodeyn commented 1 year ago

Same here. I am surprised this was not noticed before the release? If it was, it should of been fixed before the release.

Esbuild is still described as a feature to try out and explicitly not production ready at the guide page for it.

But if there was a known difference between package managers it should have been mentioned in the guide. In any case it needs to be added to the current list of known issues now.

JeanMeche commented 1 year ago

@LorinRenodeyn There is a pending PR to update the docs angular/angular#51006 !

spock123 commented 1 year ago

We are using 16.1.5 and Pnpm with Tailwind, and ESBuild.

Even for a very small project, rebuilds are 12 seconds consistently, while it used to be less than a second. Not sure what's going on

Edit: reverting to the old build: rebuilds are now 1 second, so 12x faster. I assume this is the Sass/EsBuild @import/@use issue. Will have to stick to the old builder until this is somehow resolved. :(

Edit2: I'm also using pnpm so that's probably the reason.. oh well

Edit3: NG16.2 seems to have resolved the issues

eneajaho commented 1 year ago

We are using 16.1.5 and Pnpm with Tailwind, and ESBuild.

Even for a very small project, rebuilds are 12 seconds consistently, while it used to be less than a second. Not sure what's going on

Edit: reverting to the old build: rebuilds are now 1 second, so 12x faster. I assume this is the Sass/EsBuild @import/@use issue. Will have to stick to the old builder until this is somehow resolved. :(

Edit2: I'm also using pnpm so that's probably the reason.. oh well

Can you try switching to npm or yarn for a test? I tried on my projects and it made a really big diff.

JeanMeche commented 1 year ago

@spock123 You should see improvements with the 16.2 !

There are several perfs improvement shipped with #25548 and #25534 !

spock123 commented 1 year ago

@JeanMeche Yes it's much much better in 16.2!! Now I just need i18n support but that's another matter /s

spock123 commented 1 year ago

@eneajaho Yes npm/yarn were much faster but I have to use pnpm as the app is part of a large monorepo with 10+ apps.

Cheers

nickbullock commented 11 months ago

hey, does anyone experience slower build times than they were in angular 15 using webpack? we've got 2x times slower builds by just migrating from angular 15 to 16

clydin commented 11 months ago

Closing as this specific issue should be addressed with improvements in 16.2. If you are still seeing performance issues, please try the latest v17 prereleases which have a significant amount of improvements over 16.x.

angular-automatic-lock-bot[bot] commented 10 months ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.