From 9e338e1baae8c738e5666d48893dc761aaecbf0e Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Fri, 17 Oct 2025 14:41:50 -0400 Subject: [PATCH] refactor(@angular/build): allow Bazel to inject a custom esbuild plugin Introduces a mechanism to dynamically load a custom esbuild plugin when the application builder is executed within a Bazel environment. This is enabled by a new `bazelEsbuildPluginPath` option, which is derived from the `NG_INTERNAL_ESBUILD_PLUGINS_DO_NOT_USE` environment variable. The path is only resolved if the `BAZEL_BINDIR` and `JS_BINARY__EXECROOT` environment variables are also present, ensuring the logic is only active during a Bazel build. The builder dynamically imports the plugin from the specified path and adds it to the esbuild pipeline, allowing for build-system-specific customizations. (cherry picked from commit ec739d79e042c2b33fd84ed9aede7c88a82e167e) --- .../angular/build/src/builders/application/index.ts | 10 +++++++++- .../angular/build/src/utils/environment-options.ts | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/angular/build/src/builders/application/index.ts b/packages/angular/build/src/builders/application/index.ts index 8f11f2fd8001..b83e3b48f270 100644 --- a/packages/angular/build/src/builders/application/index.ts +++ b/packages/angular/build/src/builders/application/index.ts @@ -14,7 +14,7 @@ import { BuildOutputFileType } from '../../tools/esbuild/bundler-context'; import { createJsonBuildManifest, emitFilesToDisk } from '../../tools/esbuild/utils'; import { colors as ansiColors } from '../../utils/color'; import { deleteOutputDir } from '../../utils/delete-output-dir'; -import { useJSONBuildLogs } from '../../utils/environment-options'; +import { bazelEsbuildPluginPath, useJSONBuildLogs } from '../../utils/environment-options'; import { purgeStaleBuildCache } from '../../utils/purge-cache'; import { assertCompatibleAngularVersion } from '../../utils/version'; import { runEsBuildBuildAction } from './build-action'; @@ -56,6 +56,14 @@ export async function* buildApplicationInternal( return; } + if (bazelEsbuildPluginPath) { + extensions ??= {}; + extensions.codePlugins ??= []; + + const { default: bazelEsbuildPlugin } = await import(bazelEsbuildPluginPath); + extensions.codePlugins.push(bazelEsbuildPlugin); + } + const normalizedOptions = await normalizeOptions(context, projectName, options, extensions); if (!normalizedOptions.outputOptions.ignoreServer) { diff --git a/packages/angular/build/src/utils/environment-options.ts b/packages/angular/build/src/utils/environment-options.ts index ea06fea2d09f..d830a5095959 100644 --- a/packages/angular/build/src/utils/environment-options.ts +++ b/packages/angular/build/src/utils/environment-options.ts @@ -112,3 +112,11 @@ export const useComponentTemplateHmr = const partialSsrBuildVariable = process.env['NG_BUILD_PARTIAL_SSR']; export const usePartialSsrBuild = isPresent(partialSsrBuildVariable) && isEnabled(partialSsrBuildVariable); + +const bazelBinDirectory = process.env['BAZEL_BINDIR']; +const bazelExecRoot = process.env['JS_BINARY__EXECROOT']; + +export const bazelEsbuildPluginPath = + bazelBinDirectory && bazelExecRoot + ? process.env['NG_INTERNAL_ESBUILD_PLUGINS_DO_NOT_USE'] + : undefined;