Skip to content

Chunk optimizer assigns the same identifier to an external @angular/core namespace import and a class in the same chunk → "ɵɵdefineComponent is not a function" #33583

Description

@ChristianLoosliVGT

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

Angular 21 (@angular/build 21.x) — the same app built and ran correctly before the upgrade to Angular 22

Description

With @angular/build's default chunk-optimization pass (NG_BUILD_OPTIMIZE_CHUNKS, threshold 3), a production build of a large app that externalizes @angular/core (as Angular Native
Federation does for singleton sharing) produces chunks where the optimizer's renamer assigns the same minified identifier e to BOTH the external @angular/core namespace import AND a
component's named class expression in the same chunk. The class-expression name shadows the namespace inside the class body, so the static initializer calls <class>.ɵɵdefineComponent(...),
which is undefinedTypeError at bootstrap → blank white page.

Exact mechanism (compiled output)

import * as e from '@angular/core';                 // external namespace import → minified to "e"                                                                                                 
let e$1 = class e {                                  // class-expression name → ALSO minified to "e"                                                                                               
  static ɵfac = (o) => new (o || e)();               // e = the class (self-ref, correct)                                                                                                          
  static ɵcmp = e.ɵɵdefineComponent({ type: e });    // e.ɵɵdefineComponent: e = the class (WRONG — must be @angular/core)                                                                         
};                                                                                                                                                                                                 

Correct (non-optimized) output uses distinct names: import * as i0 from '@angular/core' + i0.ɵɵdefineComponent({ type: _MyComponent }).

It is specifically the identifier e

Measured on one real build (~130 lazy chunks importing the @angular/core namespace):

@angular/core namespace minified to… chunks of which collide
e 52 5
any other letter (t, n, a, i, o, r, s, …) ~78 0

namespace=e + class=t → fine; namespace=o + class=e → fine; only namespace=e + class=e collides. The renamer fails to deduplicate only for the letter e, and only when both a kept
external namespace import and a class-expression name in the same chunk land on it. Colliding components share no source pattern — it is purely a renamer name-allocation collision.

Same class of defect as the closed #32764rolldown/rolldown#8793 ("colliding variable names"), but still reproduces on [email protected] as bundled by @angular/[email protected].

Workaround:

  • NG_BUILD_OPTIMIZE_CHUNKS=0 — disables only the chunk-optimization pass; keeps mangling + other minification (main bundle ~126 kB vs ~129 kB).
  • NG_BUILD_MANGLE=0 — keeps full identifier names, so the namespace stays i0 and never collides.

Minimal Reproduction

A minimal synthetic reproduction could not be constructed, and the reason is diagnostic: the collision only occurs when the renamer's GLOBAL name-frequency allocation over a large, diverse module
graph happens to place the identifier e on both a kept external @angular/core namespace import and a class-expression name in the same chunk. In uniform synthetic apps (Native Federation +
optimizer, up to ~240 lazy chunks, even with ~35 imports per component and many e-namespace chunks), classes are allocated other letters (a/n/o/i) and never collide with the e namespace.

It reproduces reliably in a large Angular Native Federation host shell (~130 lazy chunks from ~270 diverse compiled components). Extensive bisection ruled out: federation infrastructure
(orchestrator, @module-federation/enhanced, share/sharedMappings config), the eager provider graph, the shared component library (an isolated MFE with 88 shared components at 157 chunks
does NOT collide), specific dependencies, experimentalDecorators, @angular/build/esbuild/native-federation versions, and raw chunk count. Two independent parts of the app each push it over
the threshold, confirming an emergent renamer-allocation effect rather than a single module.

Exception or Error

ERROR TypeError: e.ɵɵdefineComponent is not a function                                                                                                                                                    
      at <static_initializer> (https://.../chunk-XXXXXXXX.js:1:4257)                                                                                                                                        
      at https://.../chunk-XXXXXXXX.js                                                                                                                                                                      
      at https://.../main-XXXXXXXX.js                                                                                                                                                                       
  (thrown from runInitializers → the application never bootstraps → blank page)

Your Environment

Angular CLI: 22.0.3                                                                                                                                                                                       
  Node: 22.x                                                                                                                                                                                                
  Package Manager: pnpm 10.10                                                                                                                                                                               
  OS: darwin arm64                                                                                                                                                                                          
                                                                                                                                                                                                            
  Angular: 22.0.2                                                                                                                                                                                           
  ... @angular/build            22.0.3                                                                                                                                                                      
  ... @angular-devkit/*         22.0.3                                                                                                                                                                      
                                                                                                                                                                                                            
  Additional:                                                                                                                                                                                               
    @angular-architects/native-federation   22.0.5                                                                                                                                                          
    @softarc/native-federation               4.3.1                                                                                                                                                          
    rolldown (transitive via @angular/build) 1.0.3                                                                                                                                                          
    Nx                                       23.1.0                                                                                                                                                         
    TypeScript                               6.0.3

Anything else relevant?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions