Skip to content

perf(frontend): enable gzip, cutting the JS bundle from 6.8 MB to 2.0 MB - #261

Merged
roman1887 merged 1 commit into
mainfrom
perf/frontend-gzip
Aug 3, 2026
Merged

perf(frontend): enable gzip, cutting the JS bundle from 6.8 MB to 2.0 MB#261
roman1887 merged 1 commit into
mainfrom
perf/frontend-gzip

Conversation

@roman1887

Copy link
Copy Markdown
Collaborator

demo.actyze.ai is effectively unusable on anything but a fast connection.

A headless browser could not finish domcontentloaded within 60 seconds, while curl returned 200 immediately — the HTML arrives fast, then the page waits on assets.

Cause

The production bundle is 6.8 MB and was served uncompressed:

content-length: 6810665
(no content-encoding, even when the client sends Accept-Encoding: gzip)

Both nginx base images ship gzip commented out in their default config, and this server block never enabled it. So every visitor downloaded the full 6.8 MB on every cold load — 15.7s on my connection, and well past 60s on anything slower.

Fix

Measured locally against the same bundle:

bytes
without gzip 6,810,665
with gzip 2,003,129

70.6% smaller. gzip_vary on is set so caches key on Accept-Encoding and never serve a compressed body to a client that cannot decode it.

Not a regression from the hardening work

Worth stating clearly, since #241 changed the nginx base image:

  • the old nginx:alpine base also had gzip commented out
  • total JS measures 6.6 MB in both the pre-hardening image (sha-5cbc75d) and the current one

So this has always been the case. The base image change did not cause it.

Not addressed here

The bundle should not be 6.8 MB in the first place. plotly.js, xlsx, jspdf, html2canvas and codemirror are all bundled into a single main.js with no code splitting.

Compression makes the site usable today. Splitting the bundle and lazy-loading the heavy chart and export paths is the real fix and deserves its own change — 2 MB is still a lot to ship before first paint.

Deploy note

This only takes effect once the frontend image is rebuilt and redeployed.

demo.actyze.ai was effectively unusable on anything but a fast connection.
A headless browser could not finish domcontentloaded within 60 seconds, while
curl returned 200 immediately - the HTML arrives fast and then the page waits
on assets.

The production bundle is 6.8 MB and was served uncompressed:

    content-length: 6810665
    (no content-encoding, even when the client sends Accept-Encoding: gzip)

Both nginx base images ship `gzip` commented out in the default config, and
this server block never enabled it, so every visitor downloaded the full
6.8 MB on every cold load. Measured locally against the same bundle:

    without gzip   6,810,665 bytes
    with gzip      2,003,129 bytes    (70.6% smaller)

gzip_vary is set so caches key on Accept-Encoding and do not serve a
compressed body to a client that cannot decode it.

This is pre-existing rather than a regression: the old nginx:alpine base had
gzip commented out too, and the bundle measures 6.6 MB of JS in both the
pre-hardening image and the current one. The base image change in #241 did not
cause it.

Not addressed here: the bundle is large in the first place. plotly.js,
xlsx, jspdf, html2canvas and codemirror are all bundled into a single
main.js with no code splitting. Compression makes the site usable now;
splitting the bundle and lazy-loading the heavy chart and export paths is the
real fix and deserves its own change.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude Code Review

The diff is empty — no code was attached to this PR for review.

The description is well-written and the diagnosis is credible, but without the actual nginx.conf (or equivalent) change there is nothing to audit. A few things to verify once the diff is available:

Security

  • Confirm no hardcoded credentials, server tokens, or internal hostnames appear in the nginx config.
  • Check that server_tokens off; is present (or was already in place from fix(security): harden container images, gate builds on SBOM/CVE/licence policy #241).
  • Verify gzip_types is explicit and does not include image/* or binary formats where gzip provides no benefit and adds CPU overhead. It should cover at minimum text/plain text/css application/javascript application/json image/svg+xml.
  • Confirm gzip_vary on is set (the description says it is — just verify it appears in the diff).

Correctness

  • gzip_proxied any or a suitable value should be set if the container sits behind a reverse proxy or load balancer; without it, responses to proxied requests are not compressed even when the config is otherwise correct.
  • gzip_comp_level should be a mid-range value (e.g. 5 or 6) — level 9 gives diminishing returns for significant extra CPU on every request.
  • gzip_min_length should be set (e.g. 1024 bytes) so tiny responses are not needlessly compressed.

Code Quality / Architecture

  • The description correctly notes the bundle should not be 6.8 MB. Nothing in this change addresses that, which is fine, but a follow-up issue/ticket should be opened (or linked) for code-splitting plotly.js, xlsx, jspdf, html2canvas, and CodeMirror. Compressing a monolithic bundle is a stop-gap, not a solution.
  • If this touches a Dockerfile for the frontend image, confirm it does not introduce a new RUN layer that copies secrets or credentials, and that the base image pin from fix(security): harden container images, gate builds on SBOM/CVE/licence policy #241 is preserved.

Testing

  • There are no automated tests for nginx config in this repo as described. A simple CI smoke test (curl -H "Accept-Encoding: gzip" <url> -I | grep content-encoding) would be worth adding to prevent regression, but blocking the PR on this would be disproportionate.

AGPL Compliance

  • No library changes implied; no compliance concern.

Bottom line: Please attach the actual diff. The change is low-risk in principle, but the specific nginx directives need to be reviewed before approval.


Automated review by Claude Sonnet 4.6 | Context: CLAUDE.md + README.md

@roman1887
roman1887 merged commit 12ac84e into main Aug 3, 2026
32 checks passed
@roman1887
roman1887 deleted the perf/frontend-gzip branch August 3, 2026 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant