Chunk List
A sorted list of bundle chunks rendered as a proportional-bar table. Pass a flat list of chunks tagged with a type (vendor / runtime / app / async) and an optional entry flag; the widget sorts initial chunks first, draws each row's bar proportional to the largest chunk, and surfaces the initial-load total and grand total at the top.
Preview
Dashboard build
Chunks after splitting heavy feature libs out of the initial payload.
7 chunks196 KBinitial·561 KBtotal
- vendor.js92 KB16%
- main.js78 KB14%
- shared.js22 KB4%
- runtime.js4 KB1%
- rich-editor.js145 KB26%
- pdf-renderer.js130 KB23%
- chart-lib.js90 KB16%
Customize
Chunk sizes
92KB
78KB
90KB
145KB
130KB
Options
Installation
npx shadcn@latest add https://craftbits.dev/r/chunk-list.jsonUsage
import { ChunkList } from "@craft-bits/core";
<ChunkList
title="Dashboard build"
chunks={[
{ id: "vendor", name: "vendor.js", size: 92, type: "vendor" },
{ id: "runtime", name: "runtime.js", size: 4, type: "runtime" },
{ id: "main", name: "main.js", size: 78, type: "app" },
{ id: "chart", name: "chart-lib.js", size: 90, type: "async" },
]}
/>Render a monolithic "before" by passing a single chunk:
<ChunkList
chunks={[{ id: "main", name: "main.js", size: 385, type: "app" }]}
/>Anatomy
- Header. Optional
title(renders with thecb-labelstyle) and adescriptionsub-line. Omit both for a chromeless panel. - Totals row. Chunk count on the left,
initial · totalon the right. Hide withhideTotals. - Row. Swatch + name + size on the top line; proportional bar below; role badge on the right. Bar width is
size / maxSize, so the largest chunk spans the full row. - Role tone.
vendorpaints--cb-accent,apppaints--cb-accent / 70%,asyncpaints--cb-accent / 40%,runtimepaints--cb-fg-subtle. Non-entry chunks render at 80% opacity.
Understanding the component
- Sort order. Entry chunks (initial render-blocking) sort above non-entry chunks. Within each group, rows sort by
sizedescending — the largest cost reads first.entrydefaults totruefor every type exceptasync, which defaults tofalse. - Proportional widths. Each row's bar is
chunk.size / maxSize— the visualization compares chunks against each other, not against the total. The total and the percent share live next to the size so you can read both magnitudes at once. - Type badge. The right column carries the role tag (
vendor/runtime/app/async). When a chunk is non-entry but notasync(e.g. anappchunk lifted behind a dynamic import), the badge appends alazysuffix so the deferred state stays visible. - Layout animation. Each bar uses Motion's
layoutprop with theSPRINGS.snaptoken. When sizes change, the bars resize smoothly. Underprefers-reduced-motionthe layout animation short-circuits and the bars snap.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
chunks | ChunkListChunk[] | required | Ordered list of chunks. |
title | ReactNode | — | Optional heading above the list. |
description | ReactNode | — | Optional sub-headline under the title. |
unit | string | 'KB' | Display unit suffix for sizes. |
hideTotals | boolean | false | Hide the chunk-count and initial/total row. |
hidePercent | boolean | false | Hide the per-row percent share. |
headingAs | 'h2' | 'h3' | 'h4' | 'h3' | Tag for the title element. |
ariaLabel | string | 'Bundle chunks' | Accessible label for the list. |
className | string | — | Merged onto the root via cn(). |
ChunkListChunk
| Field | Type | Description |
|---|---|---|
id | string | Stable identifier. |
name | ReactNode | Visible chunk label (e.g. main.js). |
size | number | Chunk size in the widget's unit. |
type | 'vendor' | 'runtime' | 'app' | 'async' | Role tag. Drives swatch and badge tone. Defaults to 'app'. |
entry | boolean | Whether the chunk is part of the initial payload. Defaults to true for every type except async. |
Accessibility
- The wrapper is a
<section>withdata-cb-edu="chunk-list". Rows exposedata-cb-typeanddata-cb-entryso consumers can extend per-tone styling without monkey-patching CSS. - The list is a
role="list"ofrole="listitem"entries witharia-live="polite"so size updates are announced without interrupting the user. - The totals row carries an
aria-labellikeinitial 196 KB of 561 KB totalso the headline number is conveyed without depending on color. - The bar and the type badge are decorative (
aria-hidden) — the chunk name and size are the source of truth for assistive tech. - Layout animations short-circuit under
prefers-reduced-motion.
Credits
- Extracted from:
terminal-dreams(src/components/frontend-design/perf-bundle/ui/ChunkList.tsx). The original consumed aBundleStatefrom theBundleOptLabscrollytelling engine and rendered a CSS-module table with vendor-cached / initial / on-demand tags. This rewrite drops the engine coupling and the diagram-layer palette, generalises the chunk shape to{ id, name, size, type?, entry? }, and surfaces a single sorted bar list with initial + total summaries so the widget can describe any bundle.