mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
perf(insights): defer Recharts ScatterChart imports via next/dynamic
The insights page imported seven Recharts symbols (ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer) eagerly at module top, which pulled the entire ~108 KiB Brotli Recharts chunk onto the initial bundle even though every scatter card sits inside a `length >= 5` gate below the fold. Switching each symbol to next/dynamic with `ssr: false` matches the existing HealthChart / MoodChart pattern in the same file. Recharts is still loaded once via the shared chunk graph the first time any scatter section mounts; until then, /insights ships the same JS payload as chart-free pages. Verified static-only — local pnpm build is blocked by the documented Node-25 turbopack regression. Full deltas captured in docs/audit/v15-performance.md (v1.5 phase-4 perf audit). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
210f6105a7
commit
bb2b1de742
1 file changed
+34
-9
@@ -39,15 +39,40 @@ import {
|
|||||||
TrendingUp,
|
TrendingUp,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { InsightStatusCard } from "@/components/insights/insight-status-card";
|
import { InsightStatusCard } from "@/components/insights/insight-status-card";
|
||||||
import {
|
// Recharts is ~108 KiB Brotli — defer-import the scatter primitives so they
|
||||||
ScatterChart,
|
// only land in the bundle once a correlation card actually renders. Every
|
||||||
Scatter,
|
// `<ResponsiveContainer>`/`<ScatterChart>`/`<Scatter>`/axis/grid/tooltip use
|
||||||
XAxis,
|
// site sits inside a `length >= 5` gate and is below the fold, so the first
|
||||||
YAxis,
|
// paint never waits on Recharts. v1.5 perf audit (docs/audit/v15-performance.md).
|
||||||
CartesianGrid,
|
const ScatterChart = dynamic(
|
||||||
Tooltip,
|
() => import("recharts").then((mod) => ({ default: mod.ScatterChart })),
|
||||||
ResponsiveContainer,
|
{ ssr: false },
|
||||||
} from "recharts";
|
);
|
||||||
|
const Scatter = dynamic(
|
||||||
|
() => import("recharts").then((mod) => ({ default: mod.Scatter })),
|
||||||
|
{ ssr: false },
|
||||||
|
);
|
||||||
|
const XAxis = dynamic(
|
||||||
|
() => import("recharts").then((mod) => ({ default: mod.XAxis })),
|
||||||
|
{ ssr: false },
|
||||||
|
);
|
||||||
|
const YAxis = dynamic(
|
||||||
|
() => import("recharts").then((mod) => ({ default: mod.YAxis })),
|
||||||
|
{ ssr: false },
|
||||||
|
);
|
||||||
|
const CartesianGrid = dynamic(
|
||||||
|
() => import("recharts").then((mod) => ({ default: mod.CartesianGrid })),
|
||||||
|
{ ssr: false },
|
||||||
|
);
|
||||||
|
const Tooltip = dynamic(
|
||||||
|
() => import("recharts").then((mod) => ({ default: mod.Tooltip })),
|
||||||
|
{ ssr: false },
|
||||||
|
);
|
||||||
|
const ResponsiveContainer = dynamic(
|
||||||
|
() =>
|
||||||
|
import("recharts").then((mod) => ({ default: mod.ResponsiveContainer })),
|
||||||
|
{ ssr: false },
|
||||||
|
);
|
||||||
import { getBpTargets } from "@/lib/analytics/bp-targets";
|
import { getBpTargets } from "@/lib/analytics/bp-targets";
|
||||||
import {
|
import {
|
||||||
buildTrafficRange,
|
buildTrafficRange,
|
||||||
|
|||||||
Reference in new issue
Block a user