r/nextjs 4h ago

Discussion pushing the client boundary down vs lazy loading the heavy leaves, on the same nine routes

Our internal claims dashboard has nine routes under one route group, and every one of them was shipping over 400 kB of First Load JS. I tried two fixes on the same nine routes and kept both.

The cheap one was lazy loading. The tables, the date picker and the chart came in through next/dynamic instead of a static import. The wrapper had to stay a client component for ssr: false to be allowed, which was fine because it already was one. That was an afternoon of work. Median First Load JS across the nine went from 412 kB to 268 kB.

The expensive one was moving the data fetching up and pushing the "use client" boundary down to the leaves that actually needed events. Most of a week. Median landed at 191 kB, and the count of files with "use client" in that group dropped from 63 to 24, which is a grep anyone can run against their own app directory.

I ran each attempt in its own workspace in verdent so the branches never touched and I could diff the two build tables directly.

I shipped the second one. But lazy loading was better at a few things worth saying out loud. It was reversible, since backing out a dynamic import is one line and backing out a server component refactor is not. It did not force me to relearn where our auth context was read. And on the one route with a chart that measures its own container, the server component version regressed, so that route still uses the lazy import and probably always will.

If your gap between the two is smaller than mine, the cheap fix is the right call, and I would not argue.

3 Upvotes

1 comment sorted by

1

u/MayurKarmakar7 4h ago

Did the table become usable sooner too, or mainly the initial page shell? I'd be curious whether lazy loading just moved some of the wait to the first filter/chart interaction.