Split the tool windows out of the shell, stop the idle timer storm

Performancekamo-internal
Ya
26 Agosti 2026, 01:16 UTC
Mwandishi
kamo
Ahadi ya
40d24fc

Batch 2 of the client-side performance audit. As with batch 1, nothing a member can see or do changes. The tool registry imported all ten tool windows eagerly, and ToolProviders mounts the registry unconditionally inside AuthedChrome — so every window's component tree sat in the root shell of all 143 routes for windows the dock's own comment says start empty. Measured with esbuild against just the vendor libraries this pulled in: react-markdown + remark-gfm + remark-math + rehype-katex + rehype-highlight (the AI chat bubble) is 610 KB min / 182 KB gzip, css-tree + dompurify (the message template editor) is 226 KB / 66 KB, and Quill is 205 KB / 60 KB — 1,016 KB minified / 301 KB gzip of vendor code alone, with the tool components themselves on top. All of it was downloaded, parsed and executed during hydration on every page load. Two things keep that invisible. The `icon` fields stay eager, because ToolWindowsContext reads them synchronously to re-inject a minimized window's hexhead and checks toolPlatform for truthiness before allowing a window to open at all — a lazy icon turns both into silent failures, which is the exact class of "it didn't pop up" bug this dock has had before. And the chunks are warmed rather than waited on: ToolDock preloads all ten on idle after first paint, so a click never waits on a fetch, and ToolWindowRestore preloads exactly the tools its snapshot names before replaying it, so a restored window never paints chrome around an empty body. DateTimeDisplay armed a 1 Hz interval per instance with no gate, and built its eight-timezone tooltip — with a formatter per row — in the render body whether or not the tooltip was open. On /leads that is ~60 instances: 60 timers, 60 React commits per second, and a few hundred milliseconds per second of Intl work on a grid nobody is touching. The tick is now gated on `isOpen || isHovered || format === 'relative'`, which is precisely where a live value is rendered: the tooltip header, the label while hovered (it swaps to a second-resolution counter), and a relative display that has to refresh itself. It also skips the commit while the tab is hidden, and re-reads the clock when the gate opens — without that catch-up the first hovered frame would show an age measured from whenever the tick last ran. The tooltip is a function now, so it is built only when open. The three formatters are cached per timezone. NavHighlightContext carried the hovered id and its setter in one value, so every pointer enter and leave re-rendered every consumer — including app/page.tsx, the 851-line launchpad, which only ever calls the setter and never reads the id. Sweeping across a twelve-tile grid is ~24 events, so that was ~24 full re-renders of the launchpad and every live widget on it. Split into two contexts: the setter is stable by useState contract so writers never re-render, and only the option wrappers that draw the highlight still subscribe to the id. Deliberately NOT included: moving ag-grid's two stylesheets out of globals.css. It is the single largest render-blocking win in the audit (187 KB in the <head> of every route, including /validate and /logout), but it inverts the cascade — ag-grid's CSS currently loads BEFORE Tailwind preflight and would afterwards load after it — and verifying that costs nothing visible needs a browser on /leads, /commerce and /settings/member/[id]. Left for someone who can look at it. Verified: tsc --noEmit clean; all 8 guard scripts pass; 422 tests across the nav, page, tools, chat and time suites pass, and the full suite is green except for one test belonging to another session's in-flight work.

Mabadiliko yote

Je, unaona nini kuhusu usafiri?

Kila moja ya hizi updates ardhi katika nafasi yako ya kazi moja kwa moja. Kuanza bure na kuangalia kukua wiki baada ya wiki.

Kuwa Huru MileleMtazamo wa bei