Skip to content

Incorrect initial total reporting with Rolldown based optimizer (22.1.x) #33773

Closed

Description

@imaksp

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

22.0.x

Description

Hi, Initial total considers main bundle raw size for calculation, but Rolldown optimized version has static imports of many chunks at start so it should be counted towards the total.

I also mentioned the same here before: #27715 (comment) but at that time it was experimental.
Our actual initial total for one of the app was ~2MB, now its 915.41 kB, this was found by Claude, and I confirmed it just now. (manually as Claude is down right now).

Minimal Reproduction

Build the any app with some dependencies and lazy routes with 22.0.x and 22.1.x and check difference between Initial total for both.
this is from generated main bundle with Rolldown based optimizer:

import{a as J$1,n as G$2,p as R$1,t as F$1}from"./chunk-Dss6OLyd.js";
// ...
import{a as z$2,i as te,n as Yt$1,r as de$1,t as U$1}from"./chunk-Db26sq0E.js";
// and many more as start of main bundle js

All should be counted towards the total. Rollup based version does not have such static chunk imports at start so it was accurate.

Exception or Error

NA

Your Environment

Angular CLI       : 22.1.3
Angular           : 22.1.0
Node.js           : 24.18.0
Package Manager   : pnpm 11.18.0
Operating System  : darwin arm64

┌───────────────────────────┬───────────────────┬───────────────────┐
│ Package                   │ Installed Version │ Requested Version │
├───────────────────────────┼───────────────────┼───────────────────┤
│ @angular/aria             │ 22.1.1            │ 22.1.1            │
│ @angular/build            │ 22.1.3            │ ^22.1.3           │
│ @angular/cdk              │ 22.1.1            │ 22.1.1            │
│ @angular/cli              │ 22.1.3            │ 22.1.3            │
│ @angular/common           │ 22.1.0            │ 22.1.0            │
│ @angular/compiler         │ 22.1.0            │ 22.1.0            │
│ @angular/compiler-cli     │ 22.1.0            │ 22.1.0            │
│ @angular/core             │ 22.1.0            │ 22.1.0            │
│ @angular/forms            │ 22.1.0            │ 22.1.0            │
│ @angular/platform-browser │ 22.1.0            │ 22.1.0            │
│ @angular/router           │ 22.1.0            │ 22.1.0            │
│ ng-packagr                │ 22.1.1            │ 22.1.1            │
│ rxjs                      │ 7.8.2             │ 7.8.2             │
│ typescript                │ 6.0.3             │ ~6.0.3            │
│ vitest                    │ 4.1.10            │ 4.1.10            │
└───────────────────────────┴───────────────────┴───────────────────┘

Anything else relevant?

No response

Activity

  1. changed the title [-]Incorrect initial total reporting with Rolldown base optimizer (22.1.x)[/-] [+]Incorrect initial total reporting with Rolldown based optimizer (22.1.x)[/+] on Aug 5, 2026
  2. added this to the needsTriage milestone on Aug 5, 2026
  3. alan-agius4 commented on Aug 6, 2026

    @alan-agius4
    Collaborator

    This seems like a bug but we'll need to look at a reproduction to find and fix the problem. Can you setup a minimal repro please?

    You can read here why this is needed. A good way to make a minimal repro is to create a new app via ng new repro-app and adding the minimum possible code to show the problem. Then you can push this repository to github and link it here.

    This might be related to your directory structure so its really important to get an accurate repro to diagnose this.

  4. imaksp commented on Aug 6, 2026

    @imaksp
    ContributorAuthor

    I tracked down the root cause. It is a missing Map.set in the chunk optimizer, not a metafile problem — I have opened #33793 with a one-line fix.

    The metafile is correct. Building with --stats-json, main reports its chunk imports with the right kind:

    main-32IOW7BN.js imports:
       kind=import-statement  chunk-BJebXLml.js     <-- 919.49 kB, reported as a LAZY chunk
       kind=import-statement  chunk-pTHVPgQM.js
       ... 5 more import-statement chunks
       kind=dynamic-import    dashboard-page-B88REyd_.js
       ...
    

    So BundlerContext's transitive walk classifies these correctly. They are lost afterwards.

    Root cause. optimizeChunks in packages/angular/build/src/builders/application/chunk-optimizer.ts deletes every used chunk from initialFiles, keeping only main, then re-walks the optimized graph to restore the ones main still imports statically. That walk builds a record but never stores it:

    const record = createInitialFileRecord(entryRecord.depth + 1);
    
    entriesToAnalyze.push([importPath, record]);   // never written back to initialFiles

    Because the entries were deleted just above, existingRecord is always undefined, so each chunk is analyzed and discarded. initialFiles ends up holding only the configured entry points — precisely what "Initial total" sums. The equivalent loop in BundlerContext#bundle does call initialFiles.set(...) before pushing.

    Verified. Adding that one line and rebuilding the same app, nothing else changed: 377.35 kB -> 1.35 MB (75.76 kB -> 314.70 kB transfer), with all seven statically imported chunks moving into Initial chunk files. Cross-checked by walking index.html through static import/from edges only: 1172.0 kB JS + 149.3 kB CSS, matching the corrected total.

    Why I cannot attach a minimal reproduction. The bug is only observable when the optimizer's output still contains main -> chunk static edges. In small applications Rolldown hoists all entry-reachable shared code into the main chunk, so no such chunk survives to be lost — your own chunk-optimization-server_spec.ts depends on this, asserting no chunk-*.js remains as proof the pass ran.

    On a fresh ng new with @angular/cli@22.1.3 I tried: 1 lazy route; 8 lazy routes; a shared component used by the eager and lazy graphs; a ~2 MB shared module giving a 1.72 MB main; and eight ~154 kB lazy routes sharing vendor code. Every one produced zero static chunks from main, so the totals came out correct and the test would have been vacuous. The affected application has ~114 lazy chunks. Note the misreported chunks are not all large — they range from 919 kB down to 534 bytes — so it is not purely size-driven, and I could not pin down what makes Rolldown retain them at that scale.

    Given that, a regression test asserting the invariant directly is probably more practical than a fixture app: after optimizeChunks, every entry in importsPerFile[mainFile] should be present in initialFiles. I offered in the PR to add that, or a fixture, if you can suggest a shape that keeps a shared chunk.

    Environment: @angular/cli and @angular/build 22.1.3, @angular/core 22.1.0, Node 24.18.0, production build, default NG_BUILD_OPTIMIZE_CHUNKS.

  5. imaksp commented on Aug 6, 2026

    @imaksp
    ContributorAuthor

    NOTE: above comment is generated by Claude code, it could not create reproduction as it happens only if app has so many lazy chunks.

  6. added a commit that references this issue on Aug 6, 2026
    1b59423
  7. added a commit that references this issue on Aug 6, 2026
    04b5327
  8. added a commit that references this issue on Aug 6, 2026
    46fcb29
  9. angular-automatic-lock-bot commented on Oct 18, 2026

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  10. locked and limited conversation to collaborators on Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: @angular/buildgemini-triagedLabel noting that an issue has been triaged by geminineeds: repro stepsWe cannot reproduce the issue with the information given

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions