---
title: "Bundle Analyzer"
description: "The Bundle Analyzer provides an interactive web application and command-line tool suite for inspecting, visualizing, and auditing Next.js application bundle compositions. By parsing structured bina..."
last_updated: "2026-09-23T10:52:03.135025+00:00"
canonical_url: "https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/ecosystem-packages/bundle-analyzer"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [apps/bundle-analyzer/components/index.ts](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/index.ts)
- [apps/bundle-analyzer/lib/analyze-data.ts](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts)
- [apps/bundle-analyzer/app/page.tsx](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/app/page.tsx)
- [apps/bundle-analyzer/components/treemap-visualizer.tsx](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx)
- [apps/bundle-analyzer/components/import-chain.tsx](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/import-chain.tsx)
- [packages/next/src/cli/internal/static-routes-info.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/static-routes-info.ts)
- [apps/bundle-analyzer/lib/treemap-layout.ts](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts)
- [apps/bundle-analyzer/components/sidebar.tsx](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/sidebar.tsx)
- [apps/bundle-analyzer/lib/module-graph.ts](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/module-graph.ts)
- [apps/bundle-analyzer/lib/types.ts](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/types.ts)
- [packages/next-bundle-analyzer/index.d.ts](https://github.com/blade47/next.js/blob/main/packages/next-bundle-analyzer/index.d.ts)
- [packages/next-bundle-analyzer/index.js](https://github.com/blade47/next.js/blob/main/packages/next-bundle-analyzer/index.js)
- [packages/next-bundle-analyzer/package.json](https://github.com/blade47/next.js/blob/main/packages/next-bundle-analyzer/package.json)
- [packages/next/src/cli/next-analyze.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-analyze.ts)
- [turbopack/packages/webpack-nmt/src/index.ts](https://github.com/blade47/next.js/blob/main/turbopack/packages/webpack-nmt/src/index.ts)
- [packages/next/src/next-devtools/dev-overlay/components/overview/segment-explorer.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/next-devtools/dev-overlay/components/overview/segment-explorer.tsx)
- [apps/bundle-analyzer/components.json](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components.json)
- [apps/bundle-analyzer/app/layout.tsx](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/app/layout.tsx)
- [apps/bundle-analyzer/package.json](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/package.json)
- [apps/bundle-analyzer/tsconfig.json](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/tsconfig.json)
- [packages/next/src/cli/internal/turbo-trace-server.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/internal/turbo-trace-server.ts)
- [apps/bundle-analyzer/lib/utils.ts](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/utils.ts)
- [apps/bundle-analyzer/components/ui/skeleton.tsx](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/ui/skeleton.tsx)
- [packages/next/src/bundles/webpack/packages/GraphHelpers.js](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/GraphHelpers.js)
</details>

## Overview

The Bundle Analyzer provides an interactive web application and command-line tool suite for inspecting, visualizing, and auditing Next.js application bundle compositions. By parsing structured binary payloads and module relationship graphs generated during builds, the analyzer solves the complexity of understanding heavyweight compiled outputs, large node_modules footprints, and unoptimized chunk distribution. It embodies design decisions centered around binary data views for compact storage, performant client-side treemap layout calculations, and deep dependency chain traversal. The analyzer works in tandem with build-time diagnostics and the Next.js CLI infrastructure to offer developers immediate visual insights into client and server bundle sizing.

Sources: [apps/bundle-analyzer/app/page.tsx:1-283](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/app/page.tsx#L1-L283), [apps/bundle-analyzer/lib/analyze-data.ts:208-236](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L208-L236), [packages/next/src/cli/next-analyze.ts:21-59](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-analyze.ts#L21-L59)

## Analyzer Plugin and CLI Architecture

### Overview

The bundle analysis infrastructure is exposed through two primary entry points: the `@next/bundle-analyzer` public configuration wrapper and the `next-analyze` CLI command. The configuration wrapper acts as a high-order function accepting options such as `enabled`, `openAnalyzer`, `analyzerMode`, and `logLevel`, returning a function that transforms a `NextConfig` object.

Sources: [packages/next-bundle-analyzer/index.d.ts:3-13](https://github.com/blade47/next.js/blob/main/packages/next-bundle-analyzer/index.d.ts#L3-L13), [packages/next-bundle-analyzer/index.js:1-3](https://github.com/blade47/next.js/blob/main/packages/next-bundle-analyzer/index.js#L1-L3)

### Configuration and Execution Flow

When invoked, the wrapper checks whether `enabled` is truthy and whether `process.env.TURBOPACK` is set. If Turbopack is active, a warning is emitted instructing developers to use `next experimental-analyze` or pass `--webpack` to `next build`, bypassing further modifications. Otherwise, it configures `reportFilename` based on `options.nextRuntime` and injects the `BundleAnalyzerPlugin` from `webpack-bundle-analyzer` into the Webpack configuration.

```javascript
module.exports =
  ({ enabled = true, logLevel, openAnalyzer, analyzerMode } = {}) =>
  (nextConfig = {}) => {
    if (!enabled) {
      return nextConfig
    }
    if (process.env.TURBOPACK) {
      console.warn(
        'The Next Bundle Analyzer is not compatible with Turbopack builds, no report will be generated.\n\n' +
          'Consider trying the new Turbopack analyzer via `next experimental-analyze`.\n\n' +
          'See https://nextjs.org/docs/app/guides/package-bundling for more information\n\n' +
          'To run this analysis pass the `--webpack` flag to `next build`'
      )
      return nextConfig
    }

    const extension = analyzerMode === 'json' ? '.json' : '.html'

    return Object.assign({}, nextConfig, {
      webpack(config, options) {
        const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
        config.plugins.push(
          new BundleAnalyzerPlugin({
            analyzerMode: analyzerMode || 'static',
            logLevel,
            openAnalyzer,
            reportFilename: !options.nextRuntime
              ? `./analyze/client${extension}`
              : `../${options.nextRuntime === 'nodejs' ? '../' : ''}analyze/${
                  options.nextRuntime
                }${extension}`,
          })
        )

        if (typeof nextConfig.webpack === 'function') {
          return nextConfig.webpack(config, options)
        }
        return config
      },
    })
  }
```

Sources: [packages/next-bundle-analyzer/index.js:1-41](https://github.com/blade47/next.js/blob/main/packages/next-bundle-analyzer/index.js#L1-L41)

### CLI Command Options

The `next-analyze` CLI command manages signal handlers (`SIGTERM` and `SIGINT`) to save CPU profiles before exiting, validates project directory existence via `getProjectDir()`, and delegates execution to the internal `analyze` build runner.

| Option Name | Type | Purpose |
| :--- | :--- | :--- |
| `experimentalAnalyze` | `boolean` | Activates experimental analysis modes |
| `profile` | `boolean` | Enables React production profiling during analysis |
| `mangling` | `boolean` | Controls whether variable mangling is enabled (disabling triggers a debugging warning) |
| `port` | `number` | Specifies the network port for interactive reporting servers |
| `output` | `boolean` | Toggles output generation behavior |
| `experimentalAppOnly` | `boolean` | Restricts analysis strictly to the App Router `app/` directory |

Sources: [packages/next/src/cli/next-analyze.ts:12-58](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-analyze.ts#L12-L58)

> [!WARNING]
> The `@next/bundle-analyzer` plugin explicitly aborts report generation and logs a warning if `process.env.TURBOPACK` is detected, because it relies on Webpack's plugin architecture and `webpack-bundle-analyzer`. Turbopack users must use `next experimental-analyze` instead.

Sources: [packages/next-bundle-analyzer/index.js:7-15](https://github.com/blade47/next.js/blob/main/packages/next-bundle-analyzer/index.js#L7-L15)

## Analyze Data Models and Structures

### Overview

The bundle analyzer relies on a binary-backed schema that directly mirrors Rust data models (`analyze.rs`), parsing a hybrid payload consisting of a variable-length JSON header followed by raw binary edge and dependency structures. The `AnalyzeData` class coordinates parsing of this buffer, extracting structure definitions for sources, chunk parts, output files, and modules while building index maps for fast tree traversal.

Sources: [apps/bundle-analyzer/lib/analyze-data.ts:1-236](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L1-L236)

### Data Schema Reference

The parsing pipeline handles several distinct interface structures representing the core entities of the analyzer binary format.

| Interface Name | Fields / Properties | Purpose |
| :--- | :--- | :--- |
| `AnalyzeModule` | `ident: string`, `path: string` | Represents an individual compiled module identifier and its file path |
| `AnalyzeSource` | `parent_source_index: number \| null`, `path: string` | Represents a source file node in the hierarchy, referencing its parent index |
| `AnalyzeChunkPart` | `source_index: number`, `output_file_index: number`, `size: number`, `compressed_size: number` | Maps source file segments to output files with raw and compressed sizes |
| `AnalyzeOutputFile` | `filename: string` | Stores the target emission filename for a compiled chunk |
| `AnalyzeLayer` | `name: string` | Identifies compilation layers (e.g., server, client, edge) |
| `EdgesDataReference` | `offset: number`, `length: number` | Points to a binary offset range containing packed edge lists |

Sources: [apps/bundle-analyzer/lib/analyze-data.ts:7-35](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L7-L35)

### Binary Parsing and Edge Reading Walkthrough

When an `AnalyzeData` instance is initialized with an `ArrayBuffer`, it executes a strict parsing sequence to separate the metadata header from the raw binary block:

1. `new DataView(analyzeArrayBuffer)` — Wraps the incoming buffer into a standard `DataView` interface.
2. `analyzeDataView.getUint32(0, false)` — Reads the big-endian 32-bit unsigned integer representing the byte length of the leading JSON header string.
3. `new Uint8Array(analyzeArrayBuffer, 4, analyzeJsonLength)` — Slices out the exact byte range containing the JSON-serialized header payload.
4. `TextDecoder('utf-8').decode(...)` and `JSON.parse(...)` — Decodes the UTF-8 byte array into a string and parses it into `AnalyzeDataHeader`.
5. `4 + analyzeJsonLength` — Calculates the exact byte offset where the binary section begins.
6. `new DataView(analyzeArrayBuffer, analyzeBinaryOffset)` — Instantiates the secondary `DataView` dedicated to reading edge arrays and indices.

Sources: [apps/bundle-analyzer/lib/analyze-data.ts:213-229](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L213-L229)

> [!NOTE]
> Edge data references (`EdgesDataReference`) inside the binary section store compacted adjacency lists prefixed by a `u32` count of offset entries, allowing `readEdgesDataAtIndex` to fetch specific node neighborhoods in $O(1)$ header lookup time without scanning unrequested records.

Sources: [apps/bundle-analyzer/lib/analyze-data.ts:275-323](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L275-L323)

### Path Resolution and Special Module Types

Source file paths are reconstructed dynamically by walking up the parent chain using `getFullSourcePath(index: SourceIndex)`, which recursively concatenates ancestor paths until reaching a root node where `parent_source_index` is `null`.

```typescript
export function getSpecialModuleType(
  analyzeData: AnalyzeData | undefined,
  sourceIndex: SourceIndex | null
): SpecialModule | null {
  if (!analyzeData || sourceIndex == null) return null

  const path = analyzeData.source(sourceIndex)?.path || ''
  if (path.endsWith('polyfill-module.js')) {
    return SpecialModule.POLYFILL_MODULE
  } else if (path.endsWith('polyfill-nomodule.js')) {
    return SpecialModule.POLYFILL_NOMODULE
  }

  return null
}
```

Sources: [apps/bundle-analyzer/lib/analyze-data.ts:344-354](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L344-L354), [apps/bundle-analyzer/lib/utils.ts:30-44](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/utils.ts#L30-L44)

## Treemap Layout Calculation Engine

### Overview

The treemap layout calculation engine transforms raw bundle metrics and hierarchical source trees into structured geometry nodes suitable for rendering. It manages bottom-up metadata precomputation, recursive size accumulation, path folding for single-child directories, descendant counting for collapsed viewports, and proportional subdivision via external layout routines.

Sources: [apps/bundle-analyzer/lib/treemap-layout.ts:47-290](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L47-L290)

### Call-Chain Execution Walkthrough

When the UI component triggers a layout calculation, execution flows through a precise sequence of transformation steps:

1. `TreemapVisualizer` — Initiates the rendering cycle and invokes the top-level layout generator. Sources: [apps/bundle-analyzer/components/treemap-visualizer.tsx:8-12](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L8-L12)
2. `computeTreemapLayoutFromAnalyze` — Serves as the public entry point that triggers metadata precomputation across the entire source tree before invoking internal generation logic. Sources: [apps/bundle-analyzer/lib/treemap-layout.ts:271-290](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L271-L290)
3. `precomputeSourceMetadata` — Executes a bottom-up sweep across all sources to aggregate raw byte sizes, compressed sizes, and active filter statuses. Sources: [apps/bundle-analyzer/lib/treemap-layout.ts:47-106](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L47-L106)
4. `getOwnSizes` — Inspects chunk parts associated with a given source index to compute immediate uncompressed and compressed byte totals. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:356-371](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L356-L371)
5. `chunkPart` — Retrieves specific binary chunk part structures from the analyzer header to sum file segment sizes. Sources: [apps/bundle-analyzer/lib/analyze-data.ts:252-255](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L252-L255)

```mermaid
sequenceDiagram
    participant TV as TreemapVisualizer
    participant TL as treemap-layout.ts
    participant AD as analyze-data.ts
    TV->>TL: computeTreemapLayoutFromAnalyze()
    TL->>TL: precomputeSourceMetadata()
    TL->>AD: getOwnSizes()
    AD->>AD: chunkPart()
```

Sources: [apps/bundle-analyzer/lib/analyze-data.ts:252-271](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L252-L271), [apps/bundle-analyzer/lib/treemap-layout.ts:47-290](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L47-L290), [apps/bundle-analyzer/components/treemap-visualizer.tsx:8-12](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L8-L12)

### Layout Node Types and Interfaces

The engine structures output using explicit interfaces defining geometric rectangles, metadata attributes, and node classifications.

| Interface / Enum Name | Key Fields / Members | Purpose |
| :--- | :--- | :--- |
| `LayoutRect` | `x: number`, `y: number`, `width: number`, `height: number` | Defines absolute 2D canvas positioning and dimensions for rendered rectangles |
| `LayoutNodeInfo` | `name: string`, `size: number`, `server?: boolean`, `client?: boolean`, `traced?: boolean` | Carries descriptive metrics and flags for inspection tooltips |
| `LayoutNode` | `rect: LayoutRect`, `type: 'file' \| 'directory' \| 'collapsed-directory'`, `specialModuleType: SpecialModule \| null`, `children?: LayoutNode[]`, `itemCount?: number` | Represents a fully positioned node in the treemap hierarchy |
| `SizeMode` | `Compressed = 'compressed'`, `Uncompressed = 'uncompressed'` | Controls whether layout sizing calculations rely on compressed or raw byte metrics |

Sources: [apps/bundle-analyzer/lib/treemap-layout.ts:6-45](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L6-L45)

> [!NOTE]
> Single-child directories whose combined folded path length is 40 characters or fewer are automatically compressed upward by merging their path strings with parent nodes, eliminating redundant nesting layers in the visualizer.

Sources: [apps/bundle-analyzer/lib/treemap-layout.ts:126-144](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L126-L144)

### Design Trade-Offs

| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| Bottom-up metadata precomputation (`precomputeSourceMetadata`) | Avoids redundant recursive tree traversals during geometry calculation | Requires allocating parallel metadata arrays covering all source indices upfront |
| Height-based directory collapsing (`isCollapsed = rect.height < 30`) | Preserves visual readability and prevents rendering sub-pixel clutter in tight viewports | Hides individual file blocks, requiring alternative summary counts |
| Path folding for single-child directories | Reduces vertical breadcrumb depth and conserves screen space for deeply nested modules | Obfuscates intermediate directory segments whose path length stays under the 40-character threshold |

Sources: [apps/bundle-analyzer/lib/treemap-layout.ts:47-106](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L47-L106), [apps/bundle-analyzer/lib/treemap-layout.ts:126-144](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L126-L144), [apps/bundle-analyzer/lib/treemap-layout.ts:171-201](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/treemap-layout.ts#L171-L201)

## Interactive Treemap Canvas Visualization

### Overview

The `TreemapVisualizer` component renders hierarchical bundle data onto an HTML5 Canvas, implementing search filtering, LRU-cached text measurement, theme-aware coloring, and spatial mouse interaction. It accepts layout nodes generated by `computeTreemapLayoutFromAnalyze` and manages interaction states such as hovering, node selection, focusing, and keyboard-driven resets via the Escape key.

Sources: [apps/bundle-analyzer/app/page.tsx:96-115](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/app/page.tsx#L96-L115), [apps/bundle-analyzer/components/treemap-visualizer.tsx:1-34](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L1-L34)

### Theme-Aware Coloring and Special Modules

File coloring is determined by `getFileColor()`, which inspects module classification flags (`js`, `css`, `json`, `asset`), environment attributes (`server`, `client`, `traced`), and special module types (`SpecialModule`). Special polyfill modules receive a dedicated neutral shade, while standard file types map to distinct base colors that are darkened for server environments and selectively lightened for traced modules.

| File Type / Condition | Base / Processed Color Code | Meaning / Purpose |
| :--- | :--- | :--- |
| Polyfill Module (`POLYFILL_MODULE`, `POLYFILL_NOMODULE`) | `#5f707f` | Neutral slate for client/nomodule polyfill chunks |
| JavaScript (`js`) | `#4682b4` (client) / Darkened (server) | Steel blue designating JavaScript source bundles |
| CSS (`css`) | `#8b7d9e` (client) / Darkened (server) | Muted purple designating style assets |
| JSON (`json`) | `#297a3a` (client) / Darkened (server) | Green designating JSON configuration or data files |
| Asset (`asset`) | `#da2f35` (client) / Darkened (server) | Red designating static assets and binary files |
| Default / Fallback | `#9ca3af` | Gray-400 fallback for unclassified nodes |

Sources: [apps/bundle-analyzer/components/treemap-visualizer.tsx:36-75](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L36-L75), [apps/bundle-analyzer/lib/types.ts:37-41](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/types.ts#L37-L41)

> [!WARNING]
> Server-side modules are rendered with colors darkened by 30% using `darken(0.3, color)`. If a server module is also marked as `traced`, its color is subsequently lightened by 15% using `lighten(0.15, color)` to restore visual distinguishability.

Sources: [apps/bundle-analyzer/components/treemap-visualizer.tsx:58-66](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L58-L66)

### Canvas Text Measurement and Filtering

To maintain high frame rates during rendering, text width calculations utilize an LRU-cached helper (`measureTextCached`) backed by a Map capped at 30,000 entries. Text strings exceeding available bounding box widths are shortened using `truncateTextWithEllipsisIfNeeded()`, which performs a binary search across character lengths combined with pre-measured ellipsis dimensions.

Sources: [apps/bundle-analyzer/components/treemap-visualizer.tsx:86-146](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L86-L146)

```mermaid
sequenceDiagram
    participant TV as TreemapVisualizer
    participant TC as measureTextCached()
    participant LRU as textWidthCache (Map)
    participant Ctx as CanvasRenderingContext2D
    TV->>TC: measureTextCached(ctx, text)
    TC->>LRU: Check cacheKey (`font|text`)
    alt Cache Hit
        LRU-->>TC: Return cached width & refresh LRU order
    else Cache Miss
        TC->>Ctx: ctx.measureText(text)
        Ctx-->>TC: width
        TC->>LRU: Store in cache (evict oldest if >= 30,000)
        LRU-->>TC: Return width
    end
```

Sources: [apps/bundle-analyzer/components/treemap-visualizer.tsx:86-114](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L86-L114)

### Viewport Interaction and Search Traversal

User interactions such as clicking or hovering over canvas coordinates are resolved recursively through `findNodeAtPosition()`. This function tests bounding box containment against `LayoutRect` coordinates, checking directory title bars before descending into child nodes or returning collapsed directory containers.

Sources: [apps/bundle-analyzer/components/treemap-visualizer.tsx:148-186](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L148-L186)

Search filtering evaluates active queries against node path hierarchies via `searchOriginalTreeForMatch()` and `nodeOrDescendantsMatchSearch()`. When matching against collapsed directories, the traversal checks the original underlying tree structure to ensure descendant matches correctly illuminate parent containers.

Sources: [apps/bundle-analyzer/components/treemap-visualizer.tsx:188-253](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/treemap-visualizer.tsx#L188-L253)

> [!TIP]
> Pressing the `Escape` key while focus is outside text input elements immediately resets both the selected source index and the focused source index back to the analysis root node.

Sources: [apps/bundle-analyzer/app/page.tsx:96-115](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/app/page.tsx#L96-L115)

## Module Graph and Dependency Resolution

### Overview

The module graph and dependency resolution system evaluates module indices, trace dependencies, and route entry points via Breadth-First Search traversal. It resolves active entries by scanning module identifiers against known Next.js template paths and client entry points.

Sources: [apps/bundle-analyzer/lib/module-graph.ts:12-66](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/module-graph.ts#L12-L66), [apps/bundle-analyzer/lib/module-graph.ts:69-154](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/module-graph.ts#L69-L154)

### Entry Point Activation and Heuristics

Active entry points are discovered via `computeActiveEntries()`, which inspects module identifiers against a predefined set of internal Next.js build templates and turbopack client entry points.

Sources: [apps/bundle-analyzer/lib/module-graph.ts:12-34](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/module-graph.ts#L12-L34)

```typescript
export function computeActiveEntries(
  modulesData: ModulesData,
  analyzeData: AnalyzeData
): ModuleIndex[] {
  const potentialEntryDependents = [
    'next/dist/esm/build/templates/pages.js',
    'next/dist/esm/build/templates/pages-api.js',
    'next/dist/esm/build/templates/pages-edge-api.js',
    'next/dist/esm/build/templates/edge-ssr.js',
    'next/dist/esm/build/templates/app-route.js',
    'next/dist/esm/build/templates/edge-app-route.js',
    'next/dist/esm/build/templates/app-page.js',
    'next/dist/esm/build/templates/edge-ssr-app.js',
    'next/dist/esm/build/templates/middleware.js',
    '[next]/entry/page-loader.ts',
  ]
  const potentialEntries = [
    'next/dist/client/app-next-turbopack.js',
    'next/dist/client/next-turbopack.js',
  ]
  // ...
}
```

Sources: [apps/bundle-analyzer/lib/module-graph.ts:12-32](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/module-graph.ts#L12-L32)

### Breadth-First Search Depth Mapping

The function `computeModuleDepthMap()` coordinates traversal from active entries to assign relative distance weights across the graph. Regular and traced dependencies receive an increment of `depth + 1`, whereas asynchronous dependencies receive a depth penalty increment of `depth + 1000` and are deferred into descending-sorted queues.

Sources: [apps/bundle-analyzer/lib/module-graph.ts:73-154](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/module-graph.ts#L73-L154)

> [!CAUTION]
> Async module dependencies are deferred using a priority queue sorted by depth descending (`b.depth - a.depth`). Direct insertion into the main depth map risks processing async nodes before their parent modules, leading to corrupted depth metrics.

Sources: [apps/bundle-analyzer/lib/module-graph.ts:100-118](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/module-graph.ts#L100-L118)

## Import Chain and Selection Details

### Overview

The import chain and selection details subsystem powers the contextual sidebar inspector and interactive import trace tree. It parses breadcrumb paths using segment matchers, resolves module indices from source paths, and displays granular resource metrics alongside output chunk mappings.

Sources: [apps/bundle-analyzer/components/import-chain.tsx:128-160](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/import-chain.tsx#L128-L160), [apps/bundle-analyzer/components/sidebar.tsx:38-133](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/sidebar.tsx#L38-L133)

### Call-Chain Execution Walkthrough

The traversal from an import component down to the underlying source identifier follows a structured execution sequence:

1. `ImportChain` initiates rendering and path resolution.
Sources: [apps/bundle-analyzer/components/import-chain.tsx:141-145](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/import-chain.tsx#L141-L145)

2. `getModuleIndicesFromSourceIndex` accepts a `sourceIndex` and queries the analyzer data structure.
Sources: [apps/bundle-analyzer/components/import-chain.tsx:141-145](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/import-chain.tsx#L141-L145)

3. `getFullSourcePath` walks up the parent source index chain recursively to reconstruct the complete path string.
Sources: [apps/bundle-analyzer/lib/analyze-data.ts:344-354](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L344-L354)

4. `source` retrieves the raw `AnalyzeSource` entry from the internal headers array using the final index.
Sources: [apps/bundle-analyzer/lib/analyze-data.ts:240-242](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L240-L242)

```mermaid
sequenceDiagram
    participant IC as ImportChain
    participant GMI as getModuleIndicesFromSourceIndex
    participant GFP as getFullSourcePath
    participant SRC as source

    IC->>GMI: getModuleIndicesFromSourceIndex(sourceIndex)
    GMI->>GFP: getFullSourcePath(sourceIndex)
    GFP->>SRC: source(index)
    SRC-->>GFP: AnalyzeSource
    GFP-->>GMI: fullPath string
    GMI-->>IC: moduleIndices
```

Sources: [apps/bundle-analyzer/components/import-chain.tsx:141-145](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/import-chain.tsx#L141-L145), [apps/bundle-analyzer/lib/analyze-data.ts:240-242](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L240-L242), [apps/bundle-analyzer/lib/analyze-data.ts:344-354](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L344-L354)

### Breadcrumb Path Parsing and Path Parts

Path segments are parsed using regular expressions to categorize components into common paths, package names, and infrastructure directories. The `getPathParts` function evaluates current segments against previous paths to highlight shared hierarchies.

Sources: [apps/bundle-analyzer/components/import-chain.tsx:68-115](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/import-chain.tsx#L68-L115)

| PathPart Property | Type | Purpose |
| :--- | :--- | :--- |
| `segment` | `string` | The individual directory or file path token. |
| `isCommon` | `boolean` | True if the segment matches the previous path prefix. |
| `isLastCommon` | `boolean` | True for the final overlapping segment in the shared prefix. |
| `isPackageName` | `boolean` | True if the segment forms part of a scoped or unscoped package name inside `node_modules`. |
| `isInfrastructure` | `boolean` | True if the segment resides within framework or package infrastructure paths. |

Sources: [apps/bundle-analyzer/components/import-chain.tsx:60-66](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/import-chain.tsx#L60-L66)

> [!NOTE]
> When `node_modules/` is detected within path segments, package name identification automatically accounts for scoped packages by claiming two segments when a segment starts with `@`.

Sources: [apps/bundle-analyzer/components/import-chain.tsx:93-105](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/import-chain.tsx#L93-L105)

### Design Trade-Offs

| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| Recursive parent path concatenation (`getFullSourcePath`) | Reconstructs full nested module hierarchies cleanly without storing redundant absolute strings in memory. | Deep source hierarchies incur repeated pointer traversal overhead when resolving root paths. |
| Isolated chunk compression estimation (`getOwnSizes`) | Avoids expensive cross-module compression calculations during real-time sidebar rendering. | Estimated compressed sizes may diverge from actual final gzip chunk footprints. |
| String-based identifier splitting (`splitIdent`) | Extracts template arguments, layers, and tree-shaking metadata cleanly from complex Webpack/Turbopack identifiers. | Relies on strict regex formatting assumptions (`IDENT_ATTRIBUTES_REGEXP`) which fail on non-standard identifiers. |

Sources: [apps/bundle-analyzer/lib/analyze-data.ts:344-372](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/analyze-data.ts#L344-L372), [apps/bundle-analyzer/lib/utils.ts:55-69](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/lib/utils.ts#L55-L69)

### Contextual Sidebar Inspection

The sidebar component (`Sidebar`) renders conditional inspection details based on the currently selected source index. If a source represents a built-in polyfill, it displays specific badge attributes; otherwise, it embeds the `ImportChain` component and lists associated output chunks.

Sources: [apps/bundle-analyzer/components/sidebar.tsx:70-217](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/sidebar.tsx#L70-L217)

```typescript
function SelectionDetails({
  analyzeData,
  modulesData,
  selectedSourceIndex,
  filterSource,
  moduleDepthMap,
  environmentFilter,
}: {
  analyzeData: AnalyzeData
  modulesData: ModulesData | null
  selectedSourceIndex: number
  moduleDepthMap: Map<number, number>
  environmentFilter: 'client' | 'server'
  filterSource: (sourceIndex: number) => boolean
}) {
  const specialModuleType = getSpecialModuleType(
    analyzeData,
    selectedSourceIndex
  )

  const selectedSource =
    selectedSourceIndex != null
      ? analyzeData.source(selectedSourceIndex)
      : undefined

  const hasChildModules =
    selectedSourceIndex != null &&
    analyzeData.sourceChildren(selectedSourceIndex).length > 0

  const { size, compressedSize } = analyzeData.getRecursiveSizes(
    selectedSourceIndex,
    filterSource
  )
  // ...
}
```

Sources: [apps/bundle-analyzer/components/sidebar.tsx:89-132](https://github.com/blade47/next.js/blob/main/apps/bundle-analyzer/components/sidebar.tsx#L89-L132)

## Related

- [Bundler Integration](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/development-and-diagnostics/bundler-integration)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/llms.txt) for all pages in this wiki.
