Careeroza
Reducing Client JavaScript
Move Work to the Server
- Keep
'use client'at the leaves; a client layout pulls everything below it into the bundle. - Format dates/prices, sort and filter lists, render markdown in Server Components.
- Pass server-rendered JSX as
childreninto client wrappers instead of importing it. - Use Server Actions for forms instead of client fetch logic + validation libraries.
- Prefer CSS (
:hover,details/summary, transitions) over JS for simple UI.
Long Lists
Rendering 2,000 order rows creates 2,000 DOM nodes. Paginate on the server, or virtualise on the client (render only rows in view):
Example
The maths behind list virtualisation (what libraries like @tanstack/react-virtual compute):
function visibleRange(scrollTop: number, viewport: number, rowHeight: number, total: number, overscan = 3) {
const first = Math.floor(scrollTop / rowHeight);
const count = Math.ceil(viewport / rowHeight);
const start = Math.max(0, first - overscan);
const end = Math.min(total - 1, first + count + overscan);
return { start, end, rendered: end - start + 1, offsetY: start * rowHeight };
}
const total = 2000, rowHeight = 48, viewport = 720;
for (const scrollTop of [0, 4800, 95_000]) {
console.log('scrollTop', String(scrollTop).padStart(6), JSON.stringify(visibleRange(scrollTop, viewport, rowHeight, total)));
}
console.log('DOM rows instead of', total, '-> about', visibleRange(4800, viewport, rowHeight, total).rendered);Output
scrollTop 0 {"start":0,"end":18,"rendered":19,"offsetY":0}
scrollTop 4800 {"start":97,"end":118,"rendered":22,"offsetY":4656}
scrollTop 95000 {"start":1976,"end":1997,"rendered":22,"offsetY":94848}
DOM rows instead of 2000 -> about 22