Skip to content

Split the frontend bundle: 2 MB gzipped ships before first paint #262

Description

@roman1887

Problem

The production JavaScript bundle is a single 6.8 MB main.js with no code splitting. Enabling gzip in #261 brought the transfer down to 2.0 MB, which made the site usable again — but 2 MB before first paint is still a lot, and compression is a mitigation rather than a fix.

Before #261 this made demo.actyze.ai effectively unusable: a headless browser could not finish domcontentloaded within 60 seconds on a normal connection.

What is in the bundle

From frontend/package.json, all of these are pulled into the single entry chunk:

Package Why it is heavy
plotly.js-dist-min ~3 MB on its own; the largest single contributor
xlsx spreadsheet export
jspdf PDF export
html2canvas screenshot/export path
@uiw/react-codemirror + @codemirror/lang-sql SQL editor
@mui/material + @mui/icons-material UI framework

Most of these are only needed on specific screens or user actions. A user who opens the dashboard and never exports anything still downloads xlsx, jspdf and html2canvas.

Suggested approach

  1. Measure first. Add source-map-explorer or webpack-bundle-analyzer and record what the actual split looks like — the table above is inferred from dependencies, not measured.
  2. Lazy-load the obvious candidates with React.lazy() + Suspense:
    • the export paths (xlsx, jspdf, html2canvas) behind the export buttons
    • the SQL editor (codemirror) behind the query view
    • Plotly behind the chart components
  3. Consider plotly.js-basic-dist-min instead of the full distribution if only standard chart types are used. This alone could remove a large fraction.
  4. Route-level splitting via React.lazy on the router.

Note on tooling

The app is on react-scripts@5.0.1 (Create React App), which is unmaintained and gives limited control over chunking. Migrating to Vite would make this substantially easier and is worth evaluating as part of the work — though it should be a deliberate decision, not a side effect.

Definition of done

  • Initial JS transfer meaningfully below the current 2.0 MB gzipped
  • Export, SQL editor and chart functionality all still work
  • A bundle size budget enforced in CI so this cannot silently regress again

Context

Compression is already in place (#261), so this is no longer urgent — but it is the actual fix. Related: #261.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/frontendenhancementNew feature or requesthelp wantedExtra attention is neededperformancePage load, bundle size, query latency, resource usage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions