Cara Mengatasi Bundle Dashboard yang Membengkak dengan Recharts Menggunakan TanStack Charts
TuBrief 편집팀
2026년 8월 12일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
Jika Anda membuka halaman dashboard dan menemui jam pasir yang terus berputar hanya untuk memuat grafik, sembilan dari sepuluh kasus masalahnya ada pada Recharts. Sangat menjengkelkan melihat ukuran bundle membengkak hingga ratusan kilobyte hanya karena menambahkan beberapa grafik. Recharts terlalu terikat erat dengan siklus rekonsiliasi React DOM. Struktur UI dan pemrosesan data saling terjalin, sehingga sulit digunakan secara ringan.
Dalam situasi seperti ini, TanStack Charts menjadi alternatif yang baik. Logika visualisasinya dipisahkan ke dalam inti berbasis tata bahasa grafis (grammar of graphics). Sementara Recharts biasanya memakan lebih dari 150KiB, TanStack Charts hanya sekitar 40KiB. Ukuran bundle terpangkas hingga hampir 70%.
Masalahnya terletak pada migrasi kode produksi. Mengubah layar yang sudah berjalan dengan baik selalu terasa mencemaskan. Anda memerlukan urutan yang jelas untuk meyakinkan anggota tim dan melakukan transisi tanpa kegagalan.
Jika Anda mencoba mengubah semuanya sekaligus, akan sangat sulit untuk menemukan sumber error. Anda harus memilih satu komponen dan membagahnya secara tepat ke dalam 4 langkah.
marks dari objek deklarasi defineChart.ResponsiveContainer dan Tooltip dengan auto-scaler milik TanStack dan modul @tanstack/charts/tooltip.useMemo dan teruskan ke komponen Chart tingkat atas.Dengan mengikuti urutan ini saja, Anda dapat memotong waktu yang dibutuhkan untuk mengganti komponen grafik pertama hingga setengahnya.
`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 }}>
);
}
`
Merender ulang seluruh komponen grafik setiap kali Anda beralih mode gelap terkesan kurang elegan. TanStack Charts mendukung properti kustom CSS dan currentColor secara langsung alih-alih nilai warna yang di-hardcode.
Alih-alih mengelola warna grafik sebagai status JavaScript, masukkan ke dalam variabel CSS. Palet warna default grafik cukup dibuat untuk merujuk dari --ts-chart-1 hingga --ts-chart-6.
[data-theme='dark'].var(--ts-chart-1) ke dalam stroke atau fill pada opsi defineChart.Jika Anda mengaturnya seperti ini, desainer meminta Anda mengubah warna grafik tidak akan mengharuskan Anda menyentuh file TSX. Cukup perbaiki CSS-nya dan selesai.
`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;
}
`
Jika Anda merender 100 ribu titik menggunakan SVG, maka 100 ribu node DOM akan tercipta. Thread browser tidak akan sanggup menahannya. Kelambatan (lag) akan terlihat jelas.
Solusinya adalah menggabungkan dua hal. Beralihlah ke renderer Canvas untuk menghilangkan biaya pembuatan DOM, dan kompres data yang terlalu padat dan tidak berguna melebihi lebar piksel layar menggunakan algoritma LTTB (Largest Triangle Three Buckets). LTTB mengurangi jumlah titik sambil tetap mempertahankan karakteristik menonjol (nilai maksimum dan minimum) dari data tersebut.
`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;
}
`
Saat menangani data time-series berskala besar, kurangi ukurannya hingga sekitar 1000 menggunakan LTTB. Kemudian, aktifkan opsi spatialIndex: true untuk menurunkan kompleksitas deteksi pointer mouse. Terakhir, pasang Canvas renderer dari paket @tanstack/charts/react/canvas untuk mendapatkan 60fps.
Format dengan tag JSX yang bersarang terlalu dalam seperti Recharts sering kali memicu halusinasi pada AI assistant. Mereka kerap menciptakan properti aneh atau gagal menutup tag yang terbuka.
Library yang ditulis dengan deklarasi objek seperti TanStack Charts memungkinkan AI menghasilkan kode yang bersih selama Anda memberikan skema tipe (type schema) yang memadai. Definisikan tipe skema seperti di bawah ini dalam proyek Anda dan masukkan ke dalam prompt AI atau file aturan (.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;
};
}
`
Jika Anda menuliskan aturan dalam prompt untuk mengimpor dari subpath yang akurat seperti @tanstack/charts/scales/linear beserta aturan penggunaan useMemo, Anda dapat langsung menggunakan kode yang dihasilkan oleh AI tanpa perlu modifikasi.