From 7aa477ccdd43436ec6be8dec5f704907af990fd4 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..40dee2695294 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 === 'zone.js' || path.startsWith('zone.js/')) { + return false; + } + + return path.startsWith('.') || /\.[mc]?[jt]sx?$/.test(path); +}