From 327eca120aff6e5340296af899a7a27065da4c3c Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Mon, 2 Mar 2026 07:58:15 +0000 Subject: [PATCH] fix(@angular/build): bundle polyfills to preserve execution order in dev server When using the development server with ESM, polyfills were built as a mix of bundled local files and external package imports. Due to ESM hoisting behavior, all top-level import statements are executed before any other code in the module. This caused polyfills that modify global state (like zone-flags.js) to run after the polyfills they were intended to configure (like zone.js), rendering the flags ineffective. This change ensures that all polyfills are bundled together into the single polyfills.js file when using the development server, matching the behavior of the production build and preserving the intended execution order. Closes #32632 --- .../src/tools/esbuild/application-code-bundle.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 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 e59f139c8aeb..257a98fc0f45 100644 --- a/packages/angular/build/src/tools/esbuild/application-code-bundle.ts +++ b/packages/angular/build/src/tools/esbuild/application-code-bundle.ts @@ -654,9 +654,13 @@ function getEsBuildCommonPolyfillsOptions( tryToResolvePolyfillsAsRelative: boolean, loadResultCache: LoadResultCache | undefined, ): BuildOptions | undefined { - const { jit, workspaceRoot, i18nOptions, externalPackages } = options; + const { jit, workspaceRoot, i18nOptions } = options; - const buildOptions = getEsBuildCommonOptions(options); + const buildOptions = getEsBuildCommonOptions({ + ...options, + externalPackages: false, + }); + buildOptions.packages = 'bundle'; buildOptions.splitting = false; buildOptions.plugins ??= []; @@ -671,10 +675,8 @@ function getEsBuildCommonPolyfillsOptions( // Locale data should go first so that project provided polyfill code can augment if needed. let needLocaleDataPlugin = false; if (i18nOptions.shouldInline) { - if (!externalPackages) { - // Remove localize polyfill when i18n inline transformation have been applied to all the packages. - polyfills = polyfills.filter((path) => !path.startsWith('@angular/localize')); - } + // Remove localize polyfill when i18n inline transformation have been applied to all the packages. + polyfills = polyfills.filter((path) => !path.startsWith('@angular/localize')); // Add locale data for all active locales // TODO: Inject each individually within the inlining process itself