Skip to content

bundle-analyzer: add 'Sync only' filter toggle#92958

Open
bmaurer wants to merge 1 commit intovercel:canaryfrom
bmaurer:bundle-analyzer-sync-only-filter
Open

bundle-analyzer: add 'Sync only' filter toggle#92958
bmaurer wants to merge 1 commit intovercel:canaryfrom
bmaurer:bundle-analyzer-sync-only-filter

Conversation

@bmaurer
Copy link
Copy Markdown

@bmaurer bmaurer commented Apr 18, 2026

What

Adds a Sync only toggle to the bundle-analyzer toolbar that filters the treemap to show only modules reachable from an entry without crossing an async import() boundary.

Why

When analyzing a route, the treemap currently shows every reachable module, including anything behind one or more (async) hops. For example a 418KB cytoscape.esm.mjs can show up on the home-page treemap even though it's only reachable via:

page.tsx → (async) ConversationContent.tsx → (async) BlockRenderer.tsx → MermaidDiagram.tsx → mermaid → cytoscape

That makes it hard to see what's actually in the critical initial load. The data model already distinguishes sync vs async edges — this just exposes it as a filter.

How

computeModuleDepthMap already encodes this: each async hop adds 1000 to a module's depth. So any module whose depth is >= 1000 is behind at least one async boundary.

filterSource receives a sourceIndex, so we bridge through modulesData.getModuleIndiciesFromPath(fullSourcePath(sourceIndex)) and keep the source if any of its module indices has depth < 1000. Existing filters (environment, file type) are unchanged.

The toggle button sits next to the existing environment/type filters. No change to the import-chain view — it still shows the (async) markers in the chain so users can see where the boundary is.

Verification

Tested against a minimal demo app with a home page that sync-imports a small utility and uses dynamic(() => import('./HeavyChart')) where HeavyChart pulls in a 25-file big-lib/* tree.

  • Off: 199 modules, 247 KB
  • On: 164 modules, 172 KB (−25 big-lib/* files, −75 KB)

All big-lib modules landed at depth 1005–1006 in the depth map, confirming they're correctly detected as async-only.

tsc --noEmit and next build pass in apps/bundle-analyzer.

Adds a toggle in the bundle-analyzer toolbar that filters the treemap to
show only modules reachable from an entry without crossing an async
import() boundary. Uses the existing `computeModuleDepthMap` where
async edges add 1000 to the depth; a source is kept if any of its module
indices has depth < 1000.

Helps developers see what's actually in the initial critical path
without the noise of lazy-loaded code.
@nextjs-bot
Copy link
Copy Markdown
Collaborator

Allow CI Workflow Run

  • approve CI run for commit: bdcfa7b

Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer

@bmaurer bmaurer marked this pull request as ready for review April 18, 2026 05:37
@andrewimm andrewimm requested a review from wbinnssmith April 19, 2026 05:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants