Title: 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" · Issue #33583 · angular/angular-cli · GitHub
Open Graph Title: 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" · Issue #33583 · angular/angular-cli
X Title: 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" · Issue #33583 · angular/angular-cli
Description: 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 upg...
Open Graph Description: 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 ap...
X Description: 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 ap...
Opengraph URL: https://github.com/angular/angular-cli/issues/33583
X: @github
Domain: Github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":" 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\"","articleBody":"### Command\n\nbuild\n\n### Is this a regression?\n\n- [x] Yes, this behavior used to work in the previous version\n\n### The previous version in which this bug was not present was\n\nAngular 21 (@angular/build 21.x) — the same app built and ran correctly before the upgrade to Angular 22\n\n### Description\n\nWith `@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 \n 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 \n 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 `\u003cclass\u003e.ɵɵdefineComponent(...)`, \n which is `undefined` → `TypeError` at bootstrap → blank white page. \n \n ### Exact mechanism (compiled output) \n \n ```js \n import * as e from '@angular/core'; // external namespace import → minified to \"e\" \n let e$1 = class e { // class-expression name → ALSO minified to \"e\" \n static ɵfac = (o) =\u003e new (o || e)(); // e = the class (self-ref, correct) \n static ɵcmp = e.ɵɵdefineComponent({ type: e }); // e.ɵɵdefineComponent: e = the class (WRONG — must be @angular/core) \n }; \n ``` \n \n Correct (non-optimized) output uses distinct names: `import * as i0 from '@angular/core'` + `i0.ɵɵdefineComponent({ type: _MyComponent })`. \n \n ### It is specifically the identifier `e` \n \n Measured on one real build (~130 lazy chunks importing the `@angular/core` namespace): \n \n | `@angular/core` namespace minified to… | chunks | of which collide | \n |---|---|---| \n | `e` | 52 | 5 | \n | any other letter (t, n, a, i, o, r, s, …) | ~78 | 0 | \n \n `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 \n 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. \n \n Same class of defect as the closed angular/angular-cli#32764 → rolldown/rolldown#8793 (\"colliding variable names\"), but still reproduces on `rolldown@1.0.3` as bundled by `@angular/build@22.0.x`.\n \n **Workaround:** \n- `NG_BUILD_OPTIMIZE_CHUNKS=0` — disables only the chunk-optimization pass; keeps mangling + other minification (main bundle ~126 kB vs ~129 kB). \n- `NG_BUILD_MANGLE=0` — keeps full identifier names, so the namespace stays `i0` and never collides. \n\n### Minimal Reproduction\n\n 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\n 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 + \n 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. \n \n 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 \n (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 \n 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 \n the threshold, confirming an emergent renamer-allocation effect rather than a single module. \n\n### Exception or Error\n\n```text\nERROR TypeError: e.ɵɵdefineComponent is not a function \n at \u003cstatic_initializer\u003e (https://.../chunk-XXXXXXXX.js:1:4257) \n at https://.../chunk-XXXXXXXX.js \n at https://.../main-XXXXXXXX.js \n (thrown from runInitializers → the application never bootstraps → blank page)\n```\n\n### Your Environment\n\n```text\nAngular CLI: 22.0.3 \n Node: 22.x \n Package Manager: pnpm 10.10 \n OS: darwin arm64 \n \n Angular: 22.0.2 \n ... @angular/build 22.0.3 \n ... @angular-devkit/* 22.0.3 \n \n Additional: \n @angular-architects/native-federation 22.0.5 \n @softarc/native-federation 4.3.1 \n rolldown (transitive via @angular/build) 1.0.3 \n Nx 23.1.0 \n TypeScript 6.0.3\n```\n\n### Anything else relevant?\n\n - `chunk-optimizer.js` is byte-identical between `@angular/build` 22.0.3 and 22.0.7. \n - Forcing `esbuild@0.28.0` (vs 0.28.1) via a package-manager override does not change anything. \n - Bumping `@angular-architects/native-federation` (22.0.1 → 22.0.5) does not change anything. \n - References: angular/angular-cli#32764, rolldown/rolldown#8793.","author":{"url":"https://github.com/ChristianLoosliVGT","@type":"Person","name":"ChristianLoosliVGT"},"datePublished":"2026-07-16T10:00:10.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/33583/angular-cli/issues/33583"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:67468c07-659c-a7b2-9e1c-6e31678f4183 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | A4F2:1D457B:7578AF:A0326D:6A627D04 |
| html-safe-nonce | c0fac4962aae23ebe02d2107c32e305059fe89b6bdceea6dbcd670d6746e6004 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBNEYyOjFENDU3Qjo3NTc4QUY6QTAzMjZEOjZBNjI3RDA0IiwidmlzaXRvcl9pZCI6IjUwOTY3MTgxMjQzNTM0ODYwODUiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 2d70baa531e43dd16cc5c2ffa95be5ff178d2dbd9e2d57cf5712ba92c87c2d95 |
| hovercard-subject-tag | issue:4900872721 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/angular/angular-cli/33583/issue_layout |
| twitter:image | https://opengraph.githubassets.com/f9394e1ab3c77a3694a117d529a81205a30c9512783bf4e90baf89b30b789ffe/angular/angular-cli/issues/33583 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/f9394e1ab3c77a3694a117d529a81205a30c9512783bf4e90baf89b30b789ffe/angular/angular-cli/issues/33583 |
| og:image:alt | 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 ap... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | ChristianLoosliVGT |
| hostname | github.com |
| expected-hostname | github.com |
| None | 54d77223ecd96549586d00f1e91ee7d05feebf27ea430279a9c4ba4b7de1a93c |
| turbo-cache-control | no-preview |
| go-import | github.com/angular/angular-cli git https://github.com/angular/angular-cli.git |
| octolytics-dimension-user_id | 139426 |
| octolytics-dimension-user_login | angular |
| octolytics-dimension-repository_id | 36891867 |
| octolytics-dimension-repository_nwo | angular/angular-cli |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 36891867 |
| octolytics-dimension-repository_network_root_nwo | angular/angular-cli |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 4d79f1b99472a521fc5fb66e9fdc3ce742937dff |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width