Skip to content

@angular/build: leaves esbuild service child alive after watch:false build #33201

@Aukevanoost

Description

@Aukevanoost

Command

build

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

Symptom: After a one-shot ng build (no --watch) completes successfully, the Node process does not exit. process._getActiveHandles() shows a ChildProcess for the esbuild service

all services stopped
handles: [ 'WriteStream', 'WriteStream', 'ReadStream', 'ChildProcess' ]
requests: []
child: {
  pid: 52715,
  file: '/my/machine/<project>/node_modules/.pnpm/@esbuild+linux-x64@0.27.3/node_modules/@esbuild/linux-x64/bin/esbuild',
  args: [
    '/my/machine/<project>/node_modules/.pnpm/@esbuild+linux-x64@0.27.3/node_modules/@esbuild/linux-x64/bin/esbuild',
    '--service=0.27.3',
    '--ping'
  ]
}

The root cause lays in @angular/build/src/builders/application/build-action.js — runEsBuildBuildAction:

  • For watch:false, BundlerContext.incremental is false, so the build path uses one-shot esbuild.build() and never creates an esbuild.context().
  • ExecutionResult.dispose()BundlerContext.dispose() only awaits this.#esbuildContext?.dispose(), which is undefined in this path. So nothing tears down esbuild's long-lived
    service child.
  • The builder never calls esbuild.stop() anywhere.
  • The plugin teardown registered via build.onDispose(...) in compiler-plugin.js (javascriptTransformer.close(), cacheStore?.close(), compilation.close?.()) is fire-and-forget
    (void ...) and scheduled by esbuild via setTimeout(cb, 0), so it can race with the function returning.

The issue is not apparent in regular builds since the process is exited after the build loop marks done: true but builders that decorate over the Angular builder inherit the leakage.

Minimal Reproduction

Here's how we use the internal builder programatically: https://github.com/native-federation/angular-adapter/blob/8bd8b58b7db8ae3cac5818c2d643077a8b3161ce/packages/angular/src/builders/build/builder.ts#L95

Exception or Error


Your Environment

> ng version


     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI       : 21.2.10
Angular           : 21.2.12
Node.js           : 24.11.1
Package Manager   : pnpm 10.33.0
Operating System  : linux x64

┌───────────────────────────────┬───────────────────┬───────────────────┐
│ Package                       │ Installed Version │ Requested Version │
├───────────────────────────────┼───────────────────┼───────────────────┤
│ @angular-devkit/build-angular │ 21.2.10           │ ^21.2.10          │
│ @angular/build                │ 21.2.10           │ ^21.2.10          │
│ @angular/cli                  │ 21.2.10           │ ^21.2.10          │
│ @angular/common               │ 21.2.12           │ ^21.2.0           │
│ @angular/compiler             │ 21.2.12           │ ^21.2.0           │
│ @angular/compiler-cli         │ 21.2.12           │ ^21.2.0           │
│ @angular/core                 │ 21.2.12           │ ^21.2.0           │
│ @angular/forms                │ 21.2.12           │ ^21.2.0           │
│ @angular/platform-browser     │ 21.2.12           │ ^21.2.0           │
│ @angular/router               │ 21.2.12           │ ^21.2.0           │
│ rxjs                          │ 7.8.2             │ ~7.8.0            │
│ typescript                    │ 5.9.3             │ ~5.9.2            │
│ vitest                        │ 4.1.5             │ ^4.0.8            │
└───────────────────────────────┴───────────────────┴───────────────────┘

Anything else relevant?

This is only happening when the buildAction is called programatically

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions