Skip to content

ui: Enable React compiler and fix compiler lint violations#6289

Merged
yomete merged 12 commits intomainfrom
react-compiler-lint-violation
Apr 13, 2026
Merged

ui: Enable React compiler and fix compiler lint violations#6289
yomete merged 12 commits intomainfrom
react-compiler-lint-violation

Conversation

@yomete
Copy link
Copy Markdown
Contributor

@yomete yomete commented Apr 1, 2026

This enables React Compiler for the Parca web app and updates the codebase to satisfy the new compiler-aware React rules.

Changes

  • switch Vite from @vitejs/plugin-react-swc to @vitejs/plugin-react
  • enable babel-plugin-react-compiler targeting React 18 with compilationMode: 'infer'
  • add babel-plugin-react-compiler and react-compiler-runtime
  • upgrade eslint-plugin-react-hooks from 4.6.2 to 7.0.1

Some components are intentionally opted out because they rely on DOM measurement or third-party APIs that are not good compiler candidates right now. Those components/hooks are marked with "use no memo", so React Compiler is enabled for the app but not every component is compiled.

I was worried about build time increasing because of the switch to the Babel plugin, but that does not appear to be the case on Vercel.

Follow ups for this would be:

  • reducing the current "use no memo" opt-out list where safe
  • remove the usage of useMemo, useCallback, memo hooks.
  • Add eslint rules to discourage writing new manual memoization usage

Comparison of main vs react-compiler-lint-violation branch.

Component main Renders RC Renders Render Delta main Avg ms RC Avg ms Speed Delta
ProfileExplorerSingle 1,705 923 -46% 1.38 1.28 -7%
ProfileSelector 722 386 -47% 2.35 1.79 -24%
ProfileMetricsGraph 637 307 -52% 2.41 1.71 -29%
ProfileViewWithData 1,002 552 -45% 0.66 0.88 +33%
DashboardLayout 964 519 -46% 0.43 0.57 +33%
ProfileFlameGraph 962 517 -46% 0.40 0.53 +33%
VisualisationToolbar 61 53 -13% 2.75 2.54 -8%

Totals

Metric main React Compiler Delta
Total renders 6,053 3,257 -46%
Total render time 7,214.6ms 3,585.1ms -50%

yomete added 2 commits March 31, 2026 22:33
Ensure URL state syncs correctly with the React Compiler enabled. Navbar now reads URL params via useLocation() instead of window.location.search, and Profiles opts out of memoization so URLStateProvider's sync-from-URL effect fires on navigation.
@yomete yomete requested a review from a team as a code owner April 1, 2026 11:41
@alwaysmeticulous
Copy link
Copy Markdown

alwaysmeticulous bot commented Apr 1, 2026

✅ Meticulous spotted visual differences in 2 of 274 screens tested, but all differences have already been approved: view differences detected.

Meticulous evaluated ~5 hours of user flows against your PR.

Last updated for commit 804acbd Merge branch 'main' into react-compiler-lint-violation. This comment will update as new commits are pushed.

prevEnforcedProfileName !== enforcedProfileName ||
prevQueryExpression !== querySelection.expression
) {
setPrevEnforcedProfileName(enforcedProfileName);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just curious, do react compiler allow set states in the render block as norm?

Copy link
Copy Markdown
Contributor Author

@yomete yomete Apr 5, 2026

Choose a reason for hiding this comment

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

Yes, this is actually the React-recommended pattern for adjusting state during rendering based on prop changes.

The key requirement is that the setState call is guarded by a condition (lines 217-220), so it doesn't trigger on every render, just when the props actually change. The React compiler understands this pattern and handles it correctly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice 👍🏼

babel: {
plugins: [
[
'babel-plugin-react-compiler',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Wondering if we should do this at the component packages level too? So that the benefits gets passed on to the downstream projects too.

Might have to change the lightweight tsc only build for those packages then.

Copy link
Copy Markdown
Contributor Author

@yomete yomete Apr 5, 2026

Choose a reason for hiding this comment

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

Good point! Currently the shared packages all use tsc for builds, so the compiler only runs at the app level via Vite.

To enable it at the package level, we'd need to add Babel to the build pipeline for the React-heavy packages (components, profile, icons, hooks, dynamicsize).

I'll put up a follow-up PR for this, I want to keep this one focused on enabling the compiler at the app level and fixing the lint violations.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I went ahead to do this in this same PR and committed it here

@yomete yomete merged commit 2bb6f36 into main Apr 13, 2026
37 checks passed
@yomete yomete deleted the react-compiler-lint-violation branch April 14, 2026 09:06
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.

2 participants