Repository navigation
perf(desktop): load heavy libraries and panels on demand - #161
Conversation
Startup JavaScript (entry plus the bootstrap chunks) drops from 2,307.8 KB to 1,055.2 KB (630.1 KB to 300.7 KB gzip), measured from `bun run build`. - Mermaid loads with a dynamic import the first time a diagram renders. - KaTeX and its stylesheet load the first time a message contains math; until then the TeX source is shown in place. - The diff body (react-diff-viewer) loads on first use; the header renders at once and a placeholder reserves the diff's height. - The Doctor panel loads on demand on the error screens, guarded so a failed chunk load cannot break the screen that is reporting an error. - The Settings pages load when the Settings window first opens. The modal shell moves to pages/SettingsModal.tsx and stays eager so it still remembers the opener before taking focus. - The workspace panel loads the first time it is opened. - Fuse loads when session search opens. Closes GoDiao#152
GoDiao
left a comment
There was a problem hiding this comment.
Thanks for this, it's a really thorough first PR! We checked that the lazy boundaries are complete, and none of the moved libraries or panels are still pulled in statically from the startup path. We also checked the math fallback: it escapes TeX while KaTeX loads and re-renders once it arrives. The Settings split keeps the opener and focus handling in the eager shell. The loaders share one promise and reset it on failure. The tests would actually catch a regression, and the before/after tables made this easy to review.
One thing before merging: please remove the comments. We keep new code free of comments, JSDoc included. That rule isn't in CONTRIBUTING yet, which is on us. The ones added in this PR are:
components/chat/DiffViewer.tsxL6-7components/chat/DiffViewerBody.tsxL112-113components/chat/MermaidRenderer.tsxL30, L44components/doctor/LazyDoctorPanel.tsxL12-13, L26components/markdown/MarkdownRenderer.tsxL239, L478, and the trailing comment on L510 (keep thekatexReadydep)hooks/useSessionSearch.tsL13, L41lib/katexLoader.tsL8, L13-16, L27pages/ActiveSession.tsxL36pages/SettingsModal.tsxL9-10 (the three comments moved over fromSettings.tsxcan stay)- tests:
DiffViewer.test.tsxL19,LazyDoctorPanel.test.tsxL39,MarkdownRenderer.test.tsxL29,ActiveSession.test.tsxL600,SettingsModal.test.tsxL26
On your question about inline retry for the panels: no need. In the desktop app the chunks load from local files, and in H5 mode the app ErrorBoundary's reload already recovers.
No need to touch the CHANGELOG, we'll add the entry after merging. Once the comments are gone, we'll merge. Thanks again!
|
Thanks for the review! I've removed all the listed comments in 1d10198. The three that moved over from |
|
Merged, thanks @ibrahimmaq14! Startup JavaScript cut roughly in half is a big win, and the write-up with the before/after tables made this a pleasure to review. Thanks also for turning the cleanup around so fast. If you enjoy DreamCoder, a ⭐ on the repo would mean a lot to us. Hope to see more PRs from you! |
Closes #152
Summary
Heavy libraries and panels no longer load at startup; each one now loads the first time it is needed. Startup JavaScript drops by 54%.
Startup chunk sizes (
bun run buildindesktop/)"Startup" means the entry chunk, plus every chunk Vite preloads for the bootstrap imports in
main.tsx(App,ErrorBoundary,diagnosticsCapture,uiStore), followed transitively through static imports. This is the same walk the issue used to get its ~2.3 MB figure.main@ 939d934)App-*.jschunkLargest chunks that left the startup path: KaTeX (251 KB), Mermaid core and its dependencies (≈400 KB), react-diff-viewer with emotion (≈110 KB), the Settings pages including qrcode, Fuse, and the workspace panel.
What loads when
katex.min.cssxterm was already dynamically imported in
TerminalSettings. I left that path unchanged; it's now additionally behind the Settings and workspace boundaries.Notes for review
SettingsModalintopages/SettingsModal.tsxand lazy-load the wholeSettingspage, rather than lazy-loading each tab. The shell has to stay eager because it records the opener synchronously, before the window takes focus. Loading per tab would add a spinner on every tab switch and would have meant rewriting most of the settings tests.Settingskeeps its export frompages/Settings.tsx, so existing imports work.LazyDoctorPanel, which has a tiny error boundary that renders nothing if the chunk fails to load. Without it, a failure insideErrorBoundary's fallback would escape to the root and blank the window.ErrorBoundary, the same way a failed bootstrap import does inmain.tsxtoday. Mermaid, KaTeX and Fuse reset their cached promise on failure so a later use retries. If you'd like an inline retry for the panels (e.g. for H5 access over a flaky LAN), I can add one.Tests
bun run lint(tsc --noEmit): cleanbun run test -- --run: 114 files, 1,190 passed, 4 skipped (onmain: 111 files, 1,183 passed)bun run build: succeeds, with no new warningsNew tests:
MarkdownRenderer.lazyMath.test.tsx:MermaidRenderer.test.tsx: mermaid isn't imported until a diagram renders, then initializes withsecurityLevel: 'strict'.DiffViewer.test.tsx: the header renders immediately, the placeholder reserves height, and the body renders after loading.LazyDoctorPanel.test.tsx: the panel renders after loading, and a failed chunk load leaves the surrounding error screen intact.Updated tests: the KaTeX output tests, the SettingsModal tests, the ErrorBoundary Doctor test and the ActiveSession workspace test now wait for the lazily loaded piece before asserting.
I did not run the server tests (
bun testat the root), since this PR only touchesdesktop/. CI covers them.Manual check (Windows 11, browser mode from
docs/WEB_USAGE.md)vite build+vite preview, backend with an isolatedDREAMCODER_CONFIG_DIR):Settingschunk and rendered Providers.DoctorPaneland rendered it.MarkdownRenderer(inline + display math and a mermaid block) andDiffViewerin the page.ActiveSessiontest).