Skip to content

feat(#22): split heavy libs into separate build chunks - #30

Merged
priscaenoch merged 1 commit into
octraban:mainfrom
Hexstar-labs:feat/issue-22-bundle-splitting
Jul 22, 2026
Merged

feat(#22): split heavy libs into separate build chunks#30
priscaenoch merged 1 commit into
octraban:mainfrom
Hexstar-labs:feat/issue-22-bundle-splitting

Conversation

@Hexstar-labs

Copy link
Copy Markdown
Contributor

Closes #22

Problem

monaco-editor, 3d-force-graph, cytoscape, react-flow-renderer, @webcontainer/api, and jszip had no chunking strategy, so each got inlined into
whichever lazy route imported it first — e.g. the Sandbox route shipped a single 3.4MB (885KB gzip) chunk bundling monaco-editor + jszip +
webcontainer + app code together.

Changes

  • Added build.rollupOptions.output.manualChunks in vite.config.ts so each heavy library emits as its own chunk: monaco-editor,
    vendor-3d-force-graph, vendor-cytoscape, vendor-react-flow-renderer, vendor-jszip, vendor-webcontainer.
  • Pinned React/ReactDOM, Vite's dynamic-import preload helper, and a few small transitively-shared packages (@babel/runtime, tslib,
    d3-color/d3-interpolate/d3-timer) to an always-loaded framework chunk — without this, Rollup's automatic chunking either duplicated the React
    runtime into a vendor chunk or trapped shared helpers inside Monaco, forcing unrelated routes to download it.
  • No component/page changes needed — all six libraries were already only reachable via lazy-loaded routes (Sandbox, GraphPage, ContractPage,
    SubInvocationPage, BatchMultiCall).

Before → after

┌────────────────┬───────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Route │ Before │ After │
├────────────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Sandbox │ 3.4MB / 885KB gzip │ 16.6KB app chunk + monaco-editor 3.28MB + vendor-jszip 97KB + vendor-webcontainer 11KB │
│ │ (one chunk) │ (parallel-fetchable, independently cacheable) │
├────────────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────┤
│ BatchMultiCall │ 153KB / 45KB gzip │ 14.8KB app chunk + shared vendor-react-flow-renderer chunk │
└────────────────┴───────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────┘

Testing

  • npm run build succeeds, expected chunks present in dist
  • npx vitest run — 125/125 tests pass

Add build.rollupOptions.output.manualChunks to vite.config.ts so
monaco-editor, 3d-force-graph, cytoscape, react-flow-renderer, jszip,
and @webcontainer/api each emit as their own chunk instead of being
inlined into whichever lazy route first imports them. All of these
libraries were already only reachable through lazily-loaded route
components (Sandbox, GraphPage, ContractPage, SubInvocationPage,
BatchMultiCall), so no source changes were needed there - this was
purely a bundler config change.

Before -> after for the affected routes:
- Sandbox route chunk: one monolithic 3.4MB (885KB gzip) chunk
  bundling monaco-editor + jszip + @webcontainer/api + app code ->
  split into monaco-editor (3.28MB), vendor-jszip (97KB),
  vendor-webcontainer (11KB), and a 16.6KB Sandbox app chunk that can
  now be fetched in parallel and cached independently of app code
  changes.
- BatchMultiCall route chunk: 153KB (45KB gzip) bundling
  react-flow-renderer + app code -> split into a 14.8KB app chunk and
  a shared vendor-react-flow-renderer chunk.

Pinned React/ReactDOM, Vite's dynamic-import preload helper, and a
few small transitively-shared packages (@babel/runtime, tslib,
d3-color/d3-interpolate/d3-timer) to their own always-loaded chunk;
without this, Rollup's automatic chunking parked them inside one of
the new vendor chunks, which would have forced unrelated routes to
load that whole chunk (or, in React's case, duplicated the React
runtime into a second chunk).
@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

@Hexstar-labs is attempting to deploy a commit to the Prisca's projects Team on Vercel.

A member of the Team first needs to authorize it.

@priscaenoch
priscaenoch merged commit ae59281 into octraban:main Jul 22, 2026
1 of 2 checks passed
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
octraban Ready Ready Preview, Comment Jul 22, 2026 10:05am

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.

Split the bundle so heavy visualisation and editor dependencies load on demand

2 participants