Skip to content

feat(react-router-serve): add DISABLE_COMPRESSION environment variable - #15339

Open
kklem0 wants to merge 1 commit into
remix-run:mainfrom
kklem0:serve-disable-compression
Open

feat(react-router-serve): add DISABLE_COMPRESSION environment variable#15339
kklem0 wants to merge 1 commit into
remix-run:mainfrom
kklem0:serve-disable-compression

Conversation

@kklem0

@kklem0 kklem0 commented Jul 22, 2026

Copy link
Copy Markdown

Problem

react-router-serve unconditionally applies the compression middleware (for non-RSC builds). When the app server runs behind a CDN / edge cache that also compresses — in our case Azure Front Door — origin-side compression breaks edge caching: the origin's compressed response is chunked with no Content-Length, and when Front Door caches it, it re-serves the compressed body stamped with the uncompressed Content-Length. Clients receive a truncated body and hang waiting for the rest (we hit ~91 s stalls in production). With the origin serving identity responses, the edge compresses and caches correctly.

Today the only escape hatch is the documented one: "migrate to @react-router/express". In practice that means maintaining a full re-implementation of cli.ts in order to remove a single middleware line — a copy that silently drifts as react-router-serve evolves (ours already lagged behind the RSC handling and the absolute-base publicPath fix that landed upstream since we forked it).

Proposal

Support a DISABLE_COMPRESSION environment variable (true or 1) that skips the compression() middleware:

DISABLE_COMPRESSION=true react-router-serve build/server/index.js

Why an env var, and why this doesn't conflict with the "no customization options by design" policy:

  • Env vars are already the configuration surface of react-router-serveHOST and PORT work exactly this way. This is deployment-environment adaptation, not server customization: the middleware itself cannot detect that a compressing cache sits in front of it.
  • react-router-serve already treats compression as conditional: RSC builds run with compression fully disabled (disable compression for RSC responses for now #14381).
  • The alternative (fully ejecting to Express) forces users to fork ~200 lines of server for a one-line toggle, which seems worse for the ecosystem than one narrowly-scoped env var.

Changes

  • packages/react-router-serve/cli.ts — skip compression() when DISABLE_COMPRESSION is true/1
  • docs/api/other-api/serve.md — document the new env var alongside HOST/PORT
  • packages/react-router-serve/.changes/minor.disable-compression-env-var.md — change file
  • integration/react-router-serve-test.ts — tests asserting the default response is compressed and the DISABLE_COMPRESSION=true response is identity-encoded, against the real spawned server
  • integration/helpers/create-fixture.ts — allow passing extra env vars to the spawned react-router-serve process (additive optional param)

Testing

  • pnpm build, then playwright test --config ./integration/playwright.config.ts react-router-serve-test — all pass, including the two new compression tests (verified across chromium/firefox/webkit/msedge projects).
  • tsc for the serve package and prettier --check on all touched files pass.

Skip the compression middleware when DISABLE_COMPRESSION is set to
"true" or "1", for deployments where a proxy/CDN in front of the app
server handles compression instead (e.g. edge caches that require an
identity response with a Content-Length from the origin).
@brophdawg11 brophdawg11 added the feature-request Used to close PRs that haven't gone through/been accepted the Proposal process yet label Jul 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ CLA Signed

Thanks for signing the Contributor License Agreement.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Change File Found

One or more change files found.

Type Change
minor Add support for a DISABLE_COMPRESSION environment variable that disables the built-in compression middleware, for deployments where a proxy or CDN in front of the app server handles compression instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed feature-request Used to close PRs that haven't gone through/been accepted the Proposal process yet pkg:@react-router/serve

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants