Severity: High (perceived perf, mobile, slow connections)
sisyphus-web ships ~2.7 MB / ~780 KB gzipped to every route, including users who go straight to /settings or /upload.
Eager imports
sisyphus-web/src/App.tsx:5,47 registers AppLayout → GraphPage → GraphView synchronously, which pulls in:
react-force-graph-2d + react-force-graph-3d
three + three/examples/jsm/postprocessing/{EffectComposer,RenderPass,UnrealBloomPass}
reactflow
dagre
@uiw/react-codemirror + @codemirror/lang-{json,yaml} + @codemirror/legacy-modes
js-yaml
pako
Even if a user only opens /settings, all of this is parsed and instantiated.
Remediation
- Route-level lazy. Wrap each page component with
React.lazy():
const GraphPage = React.lazy(() => import('./components/GraphPage'));
const WorkflowEditorPage = React.lazy(() => import('./components/workflows/WorkflowEditorPage'));
const SchemaEditorPage = React.lazy(() => import('./components/schemas/SchemaEditorPage'));
const ConnectorEditorPage = React.lazy(() => import('./components/connectors/ConnectorEditorPage'));
- Three.js + post-processing. Even within
GraphView, defer the post-processing setup:
const { EffectComposer, RenderPass, UnrealBloomPass } =
await import('three/examples/jsm/postprocessing/...');
- CodeMirror language packs. Lazy-load
@codemirror/lang-yaml only on the YAML tab; same for JSON.
- Vite already does this naturally with
manualChunks — configure vite.config.ts to split vendor-three, vendor-codemirror, vendor-reactflow into separate chunks so the browser can cache them across routes.
Verification
After: target < 500 KB gzipped main bundle, with vendor-three (~400 KB gzipped) loaded only when /graph is visited.
Severity: High (perceived perf, mobile, slow connections)
sisyphus-webships ~2.7 MB / ~780 KB gzipped to every route, including users who go straight to/settingsor/upload.Eager imports
sisyphus-web/src/App.tsx:5,47registersAppLayout → GraphPage → GraphViewsynchronously, which pulls in:react-force-graph-2d+react-force-graph-3dthree+three/examples/jsm/postprocessing/{EffectComposer,RenderPass,UnrealBloomPass}reactflowdagre@uiw/react-codemirror+@codemirror/lang-{json,yaml}+@codemirror/legacy-modesjs-yamlpakoEven if a user only opens
/settings, all of this is parsed and instantiated.Remediation
React.lazy():GraphView, defer the post-processing setup:@codemirror/lang-yamlonly on the YAML tab; same for JSON.manualChunks— configurevite.config.tsto splitvendor-three,vendor-codemirror,vendor-reactflowinto separate chunks so the browser can cache them across routes.Verification
After: target < 500 KB gzipped main bundle, with
vendor-three(~400 KB gzipped) loaded only when/graphis visited.