T
TanStackβ€’6mo ago
stormy-gold

Debugging huge bundle sizes

Hey there! I've been shipping TSS in production and I noticed that even on small routes my bundle size is quite large. Over 500 kilobytes to be exact πŸ˜Άβ€πŸŒ«οΈ I don't think I quite understand how TSS/TSR is doing code splitting as the offending route is a landing page which I have explicitly isolated from the rest of the application. It does not use server functions. It does not import anything from the main application layout. It was purpose built to be a quick-loading marketing page. Its performance is good. It gets good Lighthouse/PSI scores and all of that. But that bundle size is hurting me inside. Does a massive client bundle just get shipped with every route? Or are there more things I can do to debug this?
8 Replies
correct-apricot
correct-apricotβ€’6mo ago
which bundle size exactly? the client bundle?
stormy-gold
stormy-goldOPβ€’6mo ago
yes
correct-apricot
correct-apricotβ€’6mo ago
and whats inside of that bundle? aside from react, router and start? code splitting means: there is a client bundle that contains all "base stuff" and everything that you use in the root route and then each route component will be split off (unless you configure the splitting differently) into a separate chunk so if you use some bigger deps in the root route, that will be in the client bundle
stormy-gold
stormy-goldOPβ€’6mo ago
right i get all that. i've kept my routes/__root.tsx super minimal for that reason:
import { Outlet, createRootRoute } from "@tanstack/react-router";
import appCss from "~/lib/style/tailwind.css?url";
import katexCss from "katex/dist/katex.min.css?url";
import sonnerCss from "~/lib/style/sonner.css?url";
import { Toaster } from "~/lib/components/ui/sonner";
import { HeadContent, Scripts } from "@tanstack/react-router";
import { Posthog } from "../../lib/components/posthog";
import { Suspense } from "react";

export const Route = createRootRoute({
head: () => ({
meta: [
{
charSet: "utf-8",
},
{
name: "viewport",
content: "width=device-width, initial-scale=1",
}],
links: [
{ rel: "stylesheet", href: appCss },
{ rel: "stylesheet", href: sonnerCss },
{ rel: "stylesheet", href: katexCss },
{
rel: "stylesheet",
href: "https://use.typekit.net/ayz8rge.css",
},
],
}),
component: RootComponent,
});

function RootComponent() {
return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<Outlet />
<Scripts />
<Toaster position="top-center" />
<Suspense fallback={null}>
<Posthog />
</Suspense>
</body>
</html>
);
}
import { Outlet, createRootRoute } from "@tanstack/react-router";
import appCss from "~/lib/style/tailwind.css?url";
import katexCss from "katex/dist/katex.min.css?url";
import sonnerCss from "~/lib/style/sonner.css?url";
import { Toaster } from "~/lib/components/ui/sonner";
import { HeadContent, Scripts } from "@tanstack/react-router";
import { Posthog } from "../../lib/components/posthog";
import { Suspense } from "react";

export const Route = createRootRoute({
head: () => ({
meta: [
{
charSet: "utf-8",
},
{
name: "viewport",
content: "width=device-width, initial-scale=1",
}],
links: [
{ rel: "stylesheet", href: appCss },
{ rel: "stylesheet", href: sonnerCss },
{ rel: "stylesheet", href: katexCss },
{
rel: "stylesheet",
href: "https://use.typekit.net/ayz8rge.css",
},
],
}),
component: RootComponent,
});

function RootComponent() {
return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<Outlet />
<Scripts />
<Toaster position="top-center" />
<Suspense fallback={null}>
<Posthog />
</Suspense>
</body>
</html>
);
}
I made a tiny routes/test.tsx route just to validate this:
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/test')({
component: RouteComponent,
})

function RouteComponent() {
return <div>Hello "/test"!</div>
}
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/test')({
component: RouteComponent,
})

function RouteComponent() {
return <div>Hello "/test"!</div>
}
after running build and start, i load up the route....and pull down a 500kb bundle? i just don't see where that number is coming from in this setup. that feels like its pulling the payload for the entire app.
No description
stormy-gold
stormy-goldOPβ€’6mo ago
yes i use posthog and some toast component - but surely we are nowhere near the reported 532kb.
correct-apricot
correct-apricotβ€’6mo ago
so whats inside that file?
stormy-gold
stormy-goldOPβ€’6mo ago
what appears to be minified javascript for the entire app. for example, heres a feedback box component from an entirely separate (and not imported! route):
...
x.jsx("div", {
className: "flex justify-end items-center mt-auto pt-1",
children: x.jsxs("div", {
className: "flex items-center gap-2",
children: [k.type !== "anonymous" && x.jsx(a1, {
variant: "link",
className: "text-muted-foreground hover:text-foreground items-center text-sm px-4 py-2 h-auto",
onClick: () => _(!0),
children: "Have feedback?"
}), n ? x.jsxs(z2, {
children: [x.jsx(sc, {
asChild: !0,
children: x.jsx(a1, {
variant: "secondary",
size: "icon",
"aria-label": "Stop",
onClick: s,
className: "w-10 h-10 flex-shrink-0",
children: x.jsx(JG, {
className: "w-4 h-4"
})
})
}), x.jsx(q0, {
children: "Stop"
})]
....
...
x.jsx("div", {
className: "flex justify-end items-center mt-auto pt-1",
children: x.jsxs("div", {
className: "flex items-center gap-2",
children: [k.type !== "anonymous" && x.jsx(a1, {
variant: "link",
className: "text-muted-foreground hover:text-foreground items-center text-sm px-4 py-2 h-auto",
onClick: () => _(!0),
children: "Have feedback?"
}), n ? x.jsxs(z2, {
children: [x.jsx(sc, {
asChild: !0,
children: x.jsx(a1, {
variant: "secondary",
size: "icon",
"aria-label": "Stop",
onClick: s,
className: "w-10 h-10 flex-shrink-0",
children: x.jsx(JG, {
className: "w-4 h-4"
})
})
}), x.jsx(q0, {
children: "Stop"
})]
....
correct-apricot
correct-apricotβ€’6mo ago
interesting cc @Sean Cassiere i cannot reproduce this in the start-basic example i only find the root route in the client bundle where is that feedback form component defined? and where is it imported?

Did you find this page helpful?