From 78649aed9aa262c3dd0d346ddd15f14b21a22bac Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:16:13 -0400 Subject: [PATCH] fix(@angular/build): only use external packages for polyfills when no local files are present The polyfills bundle now conditionally employs external package resolution only if no local files are detected in the polyfills array. If local files are present, all polyfills are bundled together to ensure the import execution order is correctly preserved between local and package-based entries. --- .../tools/esbuild/application-code-bundle.ts | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/angular/build/src/tools/esbuild/application-code-bundle.ts b/packages/angular/build/src/tools/esbuild/application-code-bundle.ts index 08da63744c97..f28103b34a3e 100644 --- a/packages/angular/build/src/tools/esbuild/application-code-bundle.ts +++ b/packages/angular/build/src/tools/esbuild/application-code-bundle.ts @@ -654,18 +654,19 @@ function getEsBuildCommonPolyfillsOptions( tryToResolvePolyfillsAsRelative: boolean, loadResultCache: LoadResultCache | undefined, ): BuildOptions | undefined { - const { jit, workspaceRoot, i18nOptions } = options; + const { jit, workspaceRoot, i18nOptions, externalPackages } = options; + + let polyfills = options.polyfills ? [...options.polyfills] : []; const buildOptions = getEsBuildCommonOptions({ ...options, - externalPackages: false, + // If any polyfills are local files, disable external packages for the polyfills build. + // This ensures that local files are properly bundled. + externalPackages: polyfills.some(isLocalFile) ? false : externalPackages, }); - buildOptions.packages = 'bundle'; buildOptions.splitting = false; buildOptions.plugins ??= []; - let polyfills = options.polyfills ? [...options.polyfills] : []; - // Angular JIT mode requires the runtime compiler if (jit) { polyfills.unshift('@angular/compiler'); @@ -749,3 +750,18 @@ function getEsBuildCommonPolyfillsOptions( function entryFileToWorkspaceRelative(workspaceRoot: string, entryFile: string): string { return './' + toPosixPath(relative(workspaceRoot, entryFile).replace(/.[mc]?ts$/, '')); } + +/** + * Determines if a polyfill path is a local file. + * A local file is defined as a path starting with a `.` or having a TypeScript/JavaScript extension. + * `zone.js` and its subpaths are specifically excluded and treated as packages. + * @param path The polyfill path to check. + * @returns true if the path is a local file; false otherwise. + */ +function isLocalFile(path: string): boolean { + if (path.startsWith('zone.js')) { + return false; + } + + return path[0] === '.' || /\.[mc]?[jt]sx?$/.test(path); +}