Skip to content

Vite 8: +8% bundle size and 53% more chunks compared to rolldown-vite 7.3.1 in large Angular monorepo #22007

@AlonMiz

Description

@AlonMiz

Describe the bug

Migrating a large Angular 20 monorepo from rolldown-vite@7.3.1 to vite@8.0.1 results in:

  1. +8% total JS bundle size (63.17 MB → from 58.45 MB baseline)
  2. +53% more JS files (3,206 → from 2,099)
  3. 1,276 eagerly-loaded JS files (depth 0 via static imports) vs ~1 single entry chunk in baseline

The eager/lazy split ratio is reasonable (31.51 MB eager / 31.66 MB lazy), but the sheer number of eager files creates HTTP waterfall concerns even with HTTP/2.

Reproduction

Unfortunately we cannot share the full monorepo (enterprise codebase), but here are the exact steps and measurements:

Setup:

  • Angular 20 app with ~2,000+ components
  • @analogjs/vite-plugin-angular for Angular compilation
  • Single HTML entry point → main.ts
  • Production build with Oxc minifier (default)

Baseline (rolldown-vite@7.3.1 — Rolldown-based Vite fork):

Metric Value
Total JS files 2,099
Total JS size 58.45 MB
Eager JS files ~1 (single entry chunk)
Eager JS size 29.47 MB

Vite 8.0.1 (Rolldown bundler):

Metric Value
Total JS files 3,206
Total JS size 63.17 MB
Eager JS files 1,276
Eager JS size 31.51 MB

Eager file size distribution (Vite 8):

Size range Count
> 1 MB 5
100 KB – 1 MB 45
20 KB – 100 KB 82
1 KB – 20 KB 761
< 1 KB 383

Attempted mitigations

Approach Result
advancedChunks: { minSize: 20_000 } No effect — Rolldown warns: "minSize specified without groups has no effect"
codeSplitting: { groups: [{ name: 'chunk', minSize: 20_000 }] } Too aggressive — merged everything into 1 entry chunk (55.97 MB), destroying all lazy loading
minify: 'esbuild' Slightly worse — Oxc produces smaller output (63.17 MB vs 63.81 MB)

Root cause analysis

Two separate issues contribute:

1. More granular code-splitting (chunk count)
Rolldown in Vite 8 creates more granular chunks than rolldown-vite 7.3.1. There is no minSize equivalent that selectively merges small static-import chunks without also inlining dynamic imports (see rolldown/rolldown#8707).

2. Less aggressive tree-shaking (bundle size)
Rolldown separates tree-shaking from dead code elimination in two passes (see #21939 discussion).

What is expected?

  • Bundle size parity (or close to it) with rolldown-vite 7.3.1 builds
  • A way to control chunk granularity without destroying lazy loading (e.g., minSize that only merges static-import chunks, not dynamic imports)

What is actually happening?

  • +8% total bundle size with no code changes
  • 1,276 eager files instead of ~1 entry chunk
  • No configuration-level workaround available

System Info

System:
  OS: macOS Sequoia
  Node: 20.20.0
Packages:
  vite: 8.0.1
  @analogjs/vite-plugin-angular: 1.22.1
  @angular/core: 20.0.0

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions