Skip to content

perf(web): reduce startup bundle pressure for optional runtimes#744

Closed
limityan wants to merge 3 commits into
GCWing:mainfrom
limityan:yanzhn/web-ui-bundle-p2
Closed

perf(web): reduce startup bundle pressure for optional runtimes#744
limityan wants to merge 3 commits into
GCWing:mainfrom
limityan:yanzhn/web-ui-bundle-p2

Conversation

@limityan
Copy link
Copy Markdown
Collaborator

@limityan limityan commented May 15, 2026

Summary

This PR completes the P2 and P3 Web UI bundle optimization plan without changing chunkSizeWarningLimit, without lazy-loading the main session/chat path, and without removing product-facing capabilities. The work narrows accidental startup dependencies first, then applies guarded vendor chunking once the dependency graph is cleaner.

The PR is intentionally capped at 3 commits:

  1. Document the staged bundle-splitting plan and measurement scripts.
  2. Remove accidental startup dependencies for tools, Lucide namespace icons, Mermaid, and Prism.
  3. Add P3 guarded vendor chunks plus targeted component-library hot-path import cleanup.

Optimized Scenarios

  • App startup no longer imports the public ./tools barrel just to run post-render tool initialization. Startup now uses a narrow ./tools/initializeTools entry while Git/LSP/tool barrels remain compatible.
  • Normal chat messages and plain Markdown no longer prepay Mermaid or Prism runtime cost. Mermaid loads only for Mermaid render/validate/export paths, and Prism enhances code blocks asynchronously after readable fallback text is already available.
  • Context menu, MiniApp, and smart recommendation icons now use explicit Lucide icon maps instead of namespace lookup, preserving fallback behavior for unknown names while improving tree-shaking.
  • P3 narrows @/component-library imports in chat input, pending queue, nav/session rows, model round header, and tool-card status paths so hot UI code does not go through the root component barrel unnecessarily.
  • P3 adds guarded manualChunks for React, Monaco, terminal, Markdown, Tiptap, and Lucide icons, improving cache boundaries while keeping Mermaid/Prism out of index.html preloads.

Measured Benefit

Baseline before P2:

  • Largest entry JS: 9953.0 KiB raw / 2802.0 KiB gzip
  • JS/CSS total: 14332.4 KiB raw / 3905.1 KiB gzip
  • Main entry static graph: 1067 local modules

After P2:

  • Largest entry JS: 8242.6 KiB raw / 2286.1 KiB gzip
  • JS/CSS total: 13952.4 KiB raw / 3930.0 KiB gzip
  • Main entry static graph: 1013 local modules
  • mermaid and react-syntax-highlighter are no longer statically reachable from src/web-ui/src/main.tsx

After P3:

  • Largest entry asset: vendor-monaco-DdXR92sU.js at 3771.6 KiB raw / 959.3 KiB gzip
  • App entry chunk: index-Nu1_3coB.js at 3226.0 KiB raw / 933.2 KiB gzip
  • JS/CSS total: 13952.1 KiB raw / 3880.2 KiB gzip
  • Main entry static graph: 1013 local modules
  • dist/index.html does not preload Mermaid, Prism, syntax-highlight, or react-syntax-highlighter assets

Compared with P2, P3 reduces the largest single entry JS by about 4471.0 KiB raw / 1326.8 KiB gzip, and reduces the app entry itself by about 5016.6 KiB raw / 1352.9 KiB gzip. The remaining large warnings now point at real eager hotspots such as Monaco/editor/terminal rather than one monolithic app entry.

Verification

  • pnpm run lint:web
  • pnpm run type-check:web
  • pnpm --dir src/web-ui run test:run
  • pnpm --dir src/web-ui build
  • pnpm run verify:monaco-assets
  • node scripts/report-web-bundle-size.cjs --top=26
  • node scripts/report-web-main-static-graph.cjs --assert-external-unreachable=react-syntax-highlighter --assert-external-unreachable=mermaid --assert-no-direct-import=src/web-ui/src/main.tsx:./tools --top=12
  • Select-String -Path dist\index.html -Pattern mermaid|syntax|prism|react-syntax produced no output
  • git diff --check

Note: pnpm run e2e:test:l0 was attempted during the P2 investigation, but the app shell did not become ready within 30000ms, so it is not counted as a passing verification signal.

limityan added 3 commits May 15, 2026 22:33
Add the staged Web UI bundle-splitting plan with explicit experience guardrails, P2 before/after measurements, verification gates, and deferred P3 boundaries for component-library barrels and manualChunks.

Add repeatable bundle-size and main-entry static-graph reporting scripts so future optimization stages can compare raw/gzip output and assert that optional dependencies stay out of the startup graph.
Move the app startup tool initializer onto a narrow import path, while keeping the public tool/Git/LSP barrels compatible for existing callers. This reduces accidental startup fan-out without changing the post-render Git and LSP initialization sequence.

Replace dynamic lucide namespace lookups with explicit icon maps and keep existing fallbacks, so the renderer can tree-shake unused icons without leaving context menus, MiniApp cards, or recommendations blank for unknown icon names.

Load Mermaid and Prism only when content actually needs them. Plain Markdown and chat startup no longer prepay those runtimes; code blocks and CodePreview render readable fallback text first and enhance through a cached async Prism loader.
Add guarded Vite manualChunks for React, Monaco, terminal, Markdown, Tiptap, and icon vendors so the app entry no longer carries the full startup graph as one cache unit.

Narrow component-library imports in chat, navigation, session, and tool-card hot paths while keeping the shared barrel exports available for legacy callers.

Document the P3 measurements and retain the optional Mermaid/Prism boundary by verifying those assets are not preloaded from index.html.
@limityan
Copy link
Copy Markdown
Collaborator Author

Closed in favor of #746, which now contains the stage 0-4 implementation squashed into two commits and excludes the design document from the submitted diff.

@limityan limityan closed this May 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant