TuBrief
구독 채널
비디오
커뮤니티

How to Slim Down Bloated Dashboard Bundles from Recharts with TanStack Charts

TuBrief 편집팀
2026년 8월 12일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

English한국어Español中文العربيةहिन्दीDeutschFrançaisPortuguêsРусскийBahasa Indonesia日本語

관련 영상

TanStack Did It Again... They Fixed Charts8:14

TanStack Did It Again... They Fixed Charts

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

How to Slim Down Bloated Dashboard Bundles from Recharts with TanStack Charts

If you enter a dashboard page and the hourglass spins just trying to load a chart, it's almost certainly a Recharts issue. Sighing is inevitable when you see bundle sizes inflate by hundreds of kilobytes just for adding a few charts. Recharts is tied far too closely to the React DOM reconciliation cycle. Because UI structure and data processing are tangled together, it's hard to use lightly.

TanStack Charts makes for a solid alternative in these cases. It separates visualization logic into a standalone graphics-grammar-based core. While Recharts typically consumes over 150KiB, TanStack Charts sits around 40KiB. That slims down the bundle size by close to 70%.

The catch is production code migration. Disrupting a screen that's working fine is always uneasy. Persuading team members and transitioning without breaking things requires a clear sequence.

Safely Ripping Out Recharts Code

Trying to change everything all at once makes it nearly impossible to figure out where things broke. You need to take it component by component and break it down into exactly 4 steps.

  1. Separate Data Preprocessing: First, extract data manipulation logic that was mixed inside Recharts component JSX into standalone pure functions.
  2. Mark Mapping: Move axis configurations and visual elements like lines and points into the marks array of a defineChart declaration object.
  3. Replace Utilities: Swap out ResponsiveContainer and Tooltip with TanStack's automatic scaler and the @tanstack/charts/tooltip module.
  4. Memoization: Wrap the chart definition object in useMemo and pass it to the top-level Chart component.

Following just this sequence can cut the time it takes to replace your first chart component in half.

`typescript
import React, { useMemo } from 'react';
import { defineChart, lineY, dot } from '@tanstack/charts';
import { scaleBand } from '@tanstack/charts/scales/band';
import { scaleLinear } from '@tanstack/charts/scales/linear';
import { tooltip } from '@tanstack/charts/tooltip';
import { Chart } from '@tanstack/charts/react';

interface DataRow {
date: string;
value: number;
}

export function MigratedRevenueChart({ data }: { data: DataRow[] }) {
const definition = useMemo(() => {
return defineChart({
marks: [
lineY(data, {
x: 'date',
y: 'value',
stroke: 'var(--ts-chart-1, #2563eb)',
strokeWidth: 2,
}),
dot(data, {
x: 'date',
y: 'value',
fill: 'var(--ts-chart-1, #2563eb)',
r: 4,
}),
],
x: {
scale: () => scaleBand().padding(0.2),
},
y: {
scale: scaleLinear,
nice: true,
grid: true,
},
tooltip: {
use: tooltip,
className: 'custom-tooltip',
},
});
}, [data]);

return (
<div style={{ width: '100%', height: 300 }}>


);
}

`

Eliminating JavaScript Re-renders for Dark Mode Support

It looks amateurish to re-render the entire chart component every time the dark mode toggle is flipped. TanStack Charts natively supports CSS custom properties and currentColor instead of hardcoded color values.

Stop managing chart colors in JavaScript state and push them into CSS variables. You can simply make the chart default palette reference --ts-chart-1 through --ts-chart-6.

  1. Pre-define variables for charts in the CSS root and [data-theme='dark'].
  2. Pass strings like var(--ts-chart-1) into stroke or fill within defineChart options.
  3. Manage tooltip styles using CSS classes as well and handle background colors via variables.

Setting it up this way means when a designer asks you to change chart colors, you won't need to touch the TSX files at all. Tweaking the CSS is all it takes.

`css
:root {
--bg-chart-card: #ffffff;
--text-chart-main: #172033;
--border-chart-grid: #e2e8f0;
--ts-chart-1: #2563eb;
--ts-chart-2: #f97316;
}

[data-theme='dark'] {
--bg-chart-card: #0f172a;
--text-chart-main: #f8fafc;
--border-chart-grid: #334155;
--ts-chart-1: #60a5fa;
--ts-chart-2: #fb923c;
}

.custom-tooltip {
background-color: var(--bg-chart-card);
color: var(--text-chart-main);
border: 1px solid var(--border-chart-grid);
padding: 8px 12px;
border-radius: 6px;
}

`

Making Sure It Doesn't Crash Even When Fed 100,000 Data Points

Rendering 100,000 points via SVG creates 100,000 DOM nodes. The browser thread simply cannot keep up. The stuttering is plainly visible.

The solution combines two approaches. Switch to a Canvas renderer to eliminate DOM generation overhead, and compress data that is pointlessly denser than the screen pixel width using the LTTB (Largest Triangle Three Buckets) algorithm. LTTB reduces the point count while preserving the sharp characteristics (maximums, minimums) of the data.

`typescript
export function lttbDownsample(
data: T[],
xAccessor: (d: T) => number,
yAccessor: (d: T) => number,
threshold: number
): T[] {
const dataLength = data.length;
if (threshold >= dataLength || threshold === 0) return data;

const sampled: T[] = [];
let sampledIndex = 0;
const bucketSize = (dataLength - 2) / (threshold - 2);

sampled[sampledIndex++] = data[0];

for (let i = 0; i < threshold - 2; i++) {
let avgX = 0;
let avgY = 0;
const avgRangeStart = Math.floor((i + 1) * bucketSize) + 1;
const avgRangeEnd = Math.floor((i + 2) * bucketSize) + 1;
const currentAvgRangeEnd = avgRangeEnd < dataLength ? avgRangeEnd : dataLength;

for (let j = avgRangeStart; j < currentAvgRangeEnd; j++) {
  avgX += xAccessor(data[j]);
  avgY += yAccessor(data[j]);
}
avgX /= (currentAvgRangeEnd - avgRangeStart);
avgY /= (currentAvgRangeEnd - avgRangeStart);

const rangeOffs = Math.floor((i + 0) * bucketSize) + 1;
const rangeTo = Math.floor((i + 1) * bucketSize) + 1;
const pointAX = xAccessor(sampled[sampledIndex - 1]);
const pointAY = yAccessor(sampled[sampledIndex - 1]);

let maxArea = -1;
let maxAreaPointIndex = rangeOffs;

for (let j = rangeOffs; j < rangeTo; j++) {
  const area = Math.abs(
    (pointAX - avgX) * (yAccessor(data[j]) - pointAY) -
    (pointAX - xAccessor(data[j])) * (avgY - pointAY)
  ) * 0.5;

  if (area > maxArea) {
    maxArea = area;
    maxAreaPointIndex = j;
  }
}
sampled[sampledIndex++] = data[maxAreaPointIndex];

}

sampled[sampledIndex++] = data[dataLength - 1];
return sampled;
}

`

When dealing with large-scale time-series data, use LTTB to thin it down to around 1,000 levels before passing it over. Then, enable the spatialIndex: true option to lower mouse pointer detection complexity. Finally, attach the Canvas renderer from the @tanstack/charts/react/canvas package to lock in 60fps.

How to Delegate Chart Code to Cursor or Copilot

With deeply nested JSX tag structures like Recharts, AI assistants are prone to hallucinations. They make up weird attributes or leave tags unclosed.

Libraries built with object declaration styles like TanStack Charts allow AI to pump out clean code as long as you feed it proper type schemas. Define a schema type like the one below in your project and drop it into your AI prompt or rules file (.cursorrules).

`typescript
export type ScaleType = 'linear' | 'band' | 'utc' | 'point';
export type MarkType = 'lineY' | 'barY' | 'dot' | 'areaY';

export interface AIScaleConfig {
type: ScaleType;
nice?: boolean;
grid?: boolean;
padding?: number;
}

export interface AIMarkConfig {
type: MarkType;
xKey: string;
yKey: string;
color?: string;
strokeWidth?: number;
}

export interface AIChartGenerationSchema {
data: Record<string, unknown>[];
scales: {
x: AIScaleConfig;
y: AIScaleConfig;
};
marks: AIMarkConfig[];
tooltip?: {
enabled: boolean;
className?: string;
};
}

`

Including rules in your prompt such as importing from exact subpaths (like @tanstack/charts/scales/linear) and enforcing useMemo usage ensures that the code spat out by the AI can be used immediately without modifications.