Skip to content

fix(recharts): bundle es-toolkit/compat as ESM (#6561)#6567

Closed
masenf wants to merge 3 commits into
mainfrom
claude/modest-hypatia-lm4kG
Closed

fix(recharts): bundle es-toolkit/compat as ESM (#6561)#6567
masenf wants to merge 3 commits into
mainfrom
claude/modest-hypatia-lm4kG

Conversation

@masenf
Copy link
Copy Markdown
Collaborator

@masenf masenf commented May 27, 2026

Summary

Fixes #6561. Pages that render a rx.recharts chart could crash at runtime with a TypeError and an infinite route-reload loop.

recharts default-imports the CommonJS es-toolkit/compat/* shims (get, range, sortBy, throttle, …). These are reached through recharts' shared chart utilities, so even a single chart pulls a CJS module into the bundle. Vite then emits the CJS interop helper into a chunk that isn't guaranteed to be initialized before a lazily-loaded route chunk runs, which surfaces as TypeError: … is not a function and a reload loop.

This adds a small Vite plugin to the generated vite.config.js that redirects es-toolkit/compat/<name> default-imports to the pure-ESM es-toolkit/compat barrel (it re-exports the same functions). The module graph stays ESM-only, so no CJS interop helper is emitted, and the plugin is a no-op for apps that don't import es-toolkit/compat.

Thanks @hctilf for the thorough report and reproduction.

Verification

Building a minimal import get from 'es-toolkit/compat/get' with Vite 8:

  • before: the output includes the __commonJS interop helper and throws require_isUnsafeProperty is not a function at runtime
  • after: the output is pure ESM with no interop helper, and get() still works

Also adds tests/integration/tests_playwright/test_recharts.py, which renders an area chart and asserts the SVG appears with no page errors. It runs in both dev and prod via the existing app_harness_env fixture.

Test plan

  • recharts integration test passes in CI (dev + prod)
  • existing integration tests unaffected

Generated by Claude Code

…6561)

recharts default-imports CommonJS `es-toolkit/compat/*` shims from its core
utils (ChartUtils, DataUtils), so every chart pulls CJS into the bundle. Vite's
Rolldown (prod) and Rollup (dev) emit the CJS interop helper into a chunk that
can load after React Router's lazy route chunk, so any page with a chart throws
a TypeError and reloads forever.

Add a Vite plugin that redirects `es-toolkit/compat/<name>` default-imports to
the pure-ESM `es-toolkit/compat` barrel, eliminating the CJS interop helper.
Also add a prod+dev recharts integration test that renders an area chart and
asserts no page error.

https://claude.ai/code/session_01B53hepRQu8LCtZxaxAFPSm
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 27, 2026

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing claude/modest-hypatia-lm4kG (9772e5e) with main (cf5e4ed)

Open in CodSpeed

The Vite plugin only covered the production build. In dev, Vite 8 prebundles
deps with Rolldown before the build plugins run, so recharts' CommonJS
`es-toolkit/compat/*` imports were still bundled with the broken interop helper
(TypeError: require_isUnsafeProperty is not a function). Register the same
plugin under `optimizeDeps.rolldownOptions.plugins` so the dev dependency
optimizer redirects them to the pure-ESM barrel as well.

https://claude.ai/code/session_01B53hepRQu8LCtZxaxAFPSm
@masenf
Copy link
Copy Markdown
Collaborator Author

masenf commented May 27, 2026

@greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 27, 2026

Greptile Summary

Fixes a runtime crash affecting any page with an rx.recharts chart: recharts default-imports CJS es-toolkit/compat/* shims, whose interop helper could land in a chunk that executed before it was initialized, producing a TypeError and an infinite reload loop.

  • Adds a small Vite plugin (esToolkitCompatEsm) to vite.config.js that intercepts es-toolkit/compat/<name> imports and re-exports them from the pure-ESM es-toolkit/compat barrel, eliminating the CJS interop helper from the bundle.
  • Registers the plugin in both the main plugins array and optimizeDeps.rolldownOptions.plugins so the redirect applies in both prod builds and Vite's dev pre-bundling step.
  • Adds an integration test (test_recharts.py) that renders an area chart and asserts the .recharts-surface SVG appears with no page errors, exercising both dev and prod modes.

Confidence Score: 5/5

Safe to merge — the change is a targeted, additive Vite plugin with no modification to existing logic.

The plugin is narrow in scope: it only intercepts the exact import pattern es-toolkit/compat/<identifier> and is a no-op for everything else. Both the production build path and the dev pre-bundling path are covered. The regex is correctly anchored, the virtual module ID uses the standard Vite \0 prefix, and the generated ESM re-export is syntactically valid. The integration test directly exercises the regression scenario in both dev and prod modes.

No files require special attention.

Important Files Changed

Filename Overview
packages/reflex-base/src/reflex_base/compiler/templates.py Adds a Vite plugin esToolkitCompatEsm() that intercepts es-toolkit/compat/<name> imports and redirects them to the pure-ESM barrel, eliminating the CJS interop helper that caused the crash. Correctly registered in both main plugins and optimizeDeps.rolldownOptions.plugins for dev pre-bundling.
tests/integration/tests_playwright/test_recharts.py New integration test that spins up a minimal recharts app and asserts the SVG surface is visible with no page errors; runs in both dev and prod modes via app_harness_env.
packages/reflex-base/news/6561.bugfix.md Changelog entry accurately describing the fix.

Reviews (2): Last reviewed commit: "Merge branch 'main' into claude/modest-h..." | Re-trigger Greptile

@masenf masenf marked this pull request as ready for review May 27, 2026 02:50
@masenf masenf requested a review from a team as a code owner May 27, 2026 02:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a runtime crash/infinite route-reload loop that could occur when rendering rx.recharts charts by ensuring es-toolkit/compat/* imports stay ESM-only in the Vite module graph, avoiding emission of problematic CJS interop helpers (per #6561).

Changes:

  • Add a generated Vite plugin that rewrites es-toolkit/compat/<name> default-imports to re-export from the ESM es-toolkit/compat barrel (prod build + dev dependency prebundle).
  • Add a Playwright integration test that renders a recharts chart and asserts the SVG appears with no pageerrors in both dev and prod harness modes.
  • Add a news entry documenting the regression fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
packages/reflex-base/src/reflex_base/compiler/templates.py Extends the generated vite.config.js with an ESM-redirect plugin and registers it for both build plugins and dev prebundle.
tests/integration/tests_playwright/test_recharts.py Adds regression coverage ensuring recharts renders without runtime errors in dev and prod.
packages/reflex-base/news/6561.bugfix.md Adds release-note entry describing the recharts runtime crash fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@masenf masenf marked this pull request as draft May 27, 2026 02:54
@masenf
Copy link
Copy Markdown
Collaborator Author

masenf commented May 27, 2026

this is probably the wrong layer to patch this; upstream libraries should be handling this better. a fix like this is nothing more than a compat hack

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.

Recharts components cause TypeError and infinite reload on any route

3 participants