Skip to content

feat(react-transform): add removeCall support#2423

Merged
HuJean merged 1 commit intomainfrom
feat-react-transform-remove-call
Apr 7, 2026
Merged

feat(react-transform): add removeCall support#2423
HuJean merged 1 commit intomainfrom
feat-react-transform-remove-call

Conversation

@HuJean
Copy link
Copy Markdown
Collaborator

@HuJean HuJean commented Apr 3, 2026

Summary by CodeRabbit

  • New Features

    • Added a new removeCall configuration option that removes matched runtime hook calls and replaces them with undefined in expression contexts.
  • Documentation

    • Updated configuration interfaces to reflect changes to default behaviors for function call handling options.

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).
  • Changeset added, and when a BREAKING CHANGE occurs, it needs to be clearly marked (or not required).

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 3, 2026

🦋 Changeset detected

Latest commit: d6d1899

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@lynx-js/react Minor
@lynx-js/react-webpack-plugin Minor
@lynx-js/react-rsbuild-plugin Minor
@lynx-js/react-umd Minor
@lynx-js/react-alias-rsbuild-plugin Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2026

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 3, 2026

Merging this PR will improve performance by 16.49%

⚡ 1 improved benchmark
✅ 71 untouched benchmarks
⏩ 21 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
transform 1000 view elements 47.2 ms 40.5 ms +16.49%

Comparing feat-react-transform-remove-call (d6d1899) with main (5f2cea3)

Open in CodSpeed

Footnotes

  1. 21 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@relativeci
Copy link
Copy Markdown

relativeci bot commented Apr 3, 2026

React External

#249 Bundle Size — 590.57KiB (~-0.01%).

d6d1899(current) vs 5f2cea3 main#230(baseline)

Bundle metrics  Change 1 change
                 Current
#249
     Baseline
#230
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 98.37% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 17 17
No change  Duplicate Modules 5 5
No change  Duplicate Code 8.59% 8.59%
No change  Packages 0 0
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Improvement 1 improvement
                 Current
#249
     Baseline
#230
Improvement  Other 590.57KiB (~-0.01%) 590.59KiB

Bundle analysis reportBranch feat-react-transform-remove-callProject dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci bot commented Apr 3, 2026

React MTF Example

#263 Bundle Size — 206.05KiB (0%).

d6d1899(current) vs 5f2cea3 main#244(baseline)

Bundle metrics  no changes
                 Current
#263
     Baseline
#244
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 3 3
No change  Modules 173 173
No change  Duplicate Modules 67 67
No change  Duplicate Code 45.77% 45.77%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#263
     Baseline
#244
No change  IMG 111.23KiB 111.23KiB
No change  Other 94.81KiB 94.81KiB

Bundle analysis reportBranch feat-react-transform-remove-callProject dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci bot commented Apr 3, 2026

Web Explorer

#8705 Bundle Size — 728.84KiB (0%).

d6d1899(current) vs 5f2cea3 main#8686(baseline)

Bundle metrics  Change 1 change
                 Current
#8705
     Baseline
#8686
No change  Initial JS 43.31KiB 43.31KiB
No change  Initial CSS 2.16KiB 2.16KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 8 8
No change  Assets 10 10
Change  Modules 149(-0.67%) 150
No change  Duplicate Modules 11 11
No change  Duplicate Code 34.68% 34.68%
No change  Packages 3 3
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#8705
     Baseline
#8686
No change  Other 384.62KiB 384.62KiB
No change  JS 342.07KiB 342.07KiB
No change  CSS 2.16KiB 2.16KiB

Bundle analysis reportBranch feat-react-transform-remove-callProject dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci bot commented Apr 3, 2026

React Example

#7130 Bundle Size — 236.79KiB (-0.02%).

d6d1899(current) vs 5f2cea3 main#7111(baseline)

Bundle metrics  Change 1 change
                 Current
#7130
     Baseline
#7111
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
Change  Cache Invalidation 38.46% 0%
No change  Chunks 0 0
No change  Assets 4 4
No change  Modules 179 179
No change  Duplicate Modules 70 70
No change  Duplicate Code 46.11% 46.11%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  Change 1 change Improvement 1 improvement
                 Current
#7130
     Baseline
#7111
No change  IMG 145.76KiB 145.76KiB
Improvement  Other 91.03KiB (-0.06%) 91.09KiB

Bundle analysis reportBranch feat-react-transform-remove-callProject dashboard


Generated by RelativeCIDocumentationReport issue

@HuJean HuJean force-pushed the feat-react-transform-remove-call branch from 5e4f3c5 to 2c7d396 Compare April 7, 2026 09:17
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 7, 2026

📝 Walkthrough

Walkthrough

Introduces a new removeCall configuration option to the SWC shake plugin that removes/replaces matched function calls with undefined, while resetting removeCallParams to default to an empty list. Changes span plugin implementation, type definitions, test fixtures, and webpack configuration.

Changes

Cohort / File(s) Summary
Changeset & Dependencies
.changeset/feat-react-transform-remove-call.md, packages/webpack/react-refresh-webpack-plugin/package.json
Added changeset entry for minor release of React packages with new removeCall feature. Extended peer dependency version range for @lynx-js/react-webpack-plugin to include ^0.9.0.
Core SWC Plugin Implementation
packages/react/transform/crates/swc_plugin_shake/lib.rs, packages/react/transform/crates/swc_plugin_shake/napi.rs
Introduced remove_call: Vec<String> field to ShakeVisitorConfig defaulting to ['useEffect','useLayoutEffect','__runInJS','useLynxGlobalEventListener','useImperativeHandle']. Implemented should_remove_call() predicate and extended AST visitor methods (visit_mut_stmt, visit_mut_expr) to replace matched calls with undefined or empty statements. Changed remove_call_params default to empty list. Added public API export for new field in N-API struct.
Type Definitions & Documentation
packages/react/transform/index.d.ts, packages/react/transform/swc-plugin-reactlynx/index.d.ts, packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md
Added removeCall: Array<string> property to ShakeVisitorConfig interface with documented defaults and merge behavior. Updated removeCallParams default documentation from function list to empty array across all type definition files.
Webpack Plugin Integration
packages/webpack/react-webpack-plugin/src/loaders/options.ts
Refactored getMainThreadTransformOptions to construct shake.removeCall with baseline function list merged with user options, while shake.removeCallParams is now independently configured without baseline merging.
Test Fixtures
packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_not_remove_call_in_scope_id.js, should_remove_use_effect_call.js, should_remove_use_effect_param.js, should_replace_use_effect_call_with_undefined.js
Added snapshot test fixtures covering call removal/replacement behavior, local shadowing prevention, undefined substitution in expressions, and parameter-clearing scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • lynx-family/lynx-stack#1790: Adds/extracts the swc_plugin_shake crate scaffolding that this PR extends with new removeCall visitor logic and configuration.

Suggested reviewers

  • colinaaa
  • luhc228
  • gaoachao

Poem

🐰 Hops through the AST with glee,
Calls to useEffect now set free,
removeCall shakes them clean away,
While undefined marks the day,
Whiskers twitch—this refactor's neat!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature being added: removeCall support for the react-transform component, which is the primary change across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-react-transform-remove-call

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@HuJean HuJean force-pushed the feat-react-transform-remove-call branch from 2c7d396 to e30fb69 Compare April 7, 2026 09:21
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/react/transform/swc-plugin-reactlynx/index.d.ts`:
- Around line 84-109: The ShakeVisitorConfig interface currently requires
removeCall; change it to be optional so callers can rely on runtime
defaults—update the declaration for removeCall to be optional (e.g.,
removeCall?: Array<string>) and likewise make the other fields that are
normalized at runtime (pkgName, retainProp, removeCallParams) optional on the
interface so the type matches the runtime normalization in
packages/webpack/react-webpack-plugin/src/loaders/options.ts; keep the element
types the same, only change required -> optional.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 790c5793-b435-42fd-8451-e36c2d79a4d0

📥 Commits

Reviewing files that changed from the base of the PR and between 5f2cea3 and e30fb69.

📒 Files selected for processing (12)
  • .changeset/feat-react-transform-remove-call.md
  • packages/react/transform/crates/swc_plugin_shake/lib.rs
  • packages/react/transform/crates/swc_plugin_shake/napi.rs
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_not_remove_call_in_scope_id.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_remove_use_effect_call.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_remove_use_effect_param.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_replace_use_effect_call_with_undefined.js
  • packages/react/transform/index.d.ts
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md
  • packages/webpack/react-refresh-webpack-plugin/package.json
  • packages/webpack/react-webpack-plugin/src/loaders/options.ts

@HuJean HuJean force-pushed the feat-react-transform-remove-call branch from e30fb69 to 8f20056 Compare April 7, 2026 10:24
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/react/transform/swc-plugin-reactlynx/index.d.ts (1)

84-109: ⚠️ Potential issue | 🟡 Minor

Make removeCall optional in ShakeVisitorConfig.

The removeCall field (and other fields like pkgName, retainProp, removeCallParams) should be optional since:

  1. The documentation states "The provided values will be merged with the default values"
  2. Runtime normalization handles missing values with defaults
  3. Required fields break backward compatibility for existing code constructing this interface
💡 Suggested fix
-  removeCall: Array<string>;
+  removeCall?: Array<string>;

Consider making other fields optional as well for consistency with the merge-with-defaults behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/transform/swc-plugin-reactlynx/index.d.ts` around lines 84 -
109, The ShakeVisitorConfig interface currently declares removeCall as required;
make removeCall optional (removeCall?: Array<string>) and likewise mark related
fields that are merged with defaults—pkgName, retainProp, removeCallParams—as
optional in the ShakeVisitorConfig type so callers can omit them and runtime
normalization will supply defaults; update the declaration of ShakeVisitorConfig
(and any other related config interfaces in this file) to use optional
properties to preserve backward compatibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/react/transform/swc-plugin-reactlynx/index.d.ts`:
- Around line 84-109: The ShakeVisitorConfig interface currently declares
removeCall as required; make removeCall optional (removeCall?: Array<string>)
and likewise mark related fields that are merged with defaults—pkgName,
retainProp, removeCallParams—as optional in the ShakeVisitorConfig type so
callers can omit them and runtime normalization will supply defaults; update the
declaration of ShakeVisitorConfig (and any other related config interfaces in
this file) to use optional properties to preserve backward compatibility.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 648413a5-e891-464d-b76e-8d00a957ad94

📥 Commits

Reviewing files that changed from the base of the PR and between e30fb69 and 8f20056.

📒 Files selected for processing (13)
  • .changeset/feat-react-transform-remove-call.md
  • packages/react/transform/crates/swc_plugin_shake/lib.rs
  • packages/react/transform/crates/swc_plugin_shake/napi.rs
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_not_remove_call_in_scope_id.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_remove_use_effect_call.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_remove_use_effect_param.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_replace_use_effect_call_with_undefined.js
  • packages/react/transform/index.d.ts
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md
  • packages/rspeedy/plugin-react/package.json
  • packages/webpack/react-refresh-webpack-plugin/package.json
  • packages/webpack/react-webpack-plugin/src/loaders/options.ts
✅ Files skipped from review due to trivial changes (7)
  • packages/react/transform/crates/swc_plugin_shake/tests/swc_snapshots/lib.rs/should_remove_use_effect_param.js
  • packages/rspeedy/plugin-react/package.json
  • packages/react/transform/crates/swc_plugin_shake/tests/swc_snapshots/lib.rs/should_replace_use_effect_call_with_undefined.js
  • packages/webpack/react-refresh-webpack-plugin/package.json
  • packages/react/transform/crates/swc_plugin_shake/tests/swc_snapshots/lib.rs/should_not_remove_call_in_scope_id.js
  • packages/react/transform/crates/swc_plugin_shake/tests/swc_snapshots/lib.rs/should_remove_use_effect_call.js
  • .changeset/feat-react-transform-remove-call.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/webpack/react-webpack-plugin/src/loaders/options.ts
  • packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md

upupming
upupming previously approved these changes Apr 7, 2026
@HuJean HuJean enabled auto-merge (squash) April 7, 2026 11:09
@HuJean HuJean disabled auto-merge April 7, 2026 11:26
@HuJean HuJean force-pushed the feat-react-transform-remove-call branch from 8f20056 to d6d1899 Compare April 7, 2026 11:27
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/react/transform/crates/swc_plugin_shake/lib.rs`:
- Around line 85-88: The docs claim removeCall values are merged with defaults
but the N-API path currently forwards ShakeVisitorConfig verbatim, so removeCall
replacement occurs; fix by merging the provided removeCall list with the default
hook list before constructing/passing ShakeVisitorConfig in the N-API code path
(the logic around where ShakeVisitorConfig is built/forwarded in napi.rs), or
alternatively update the docs to say removeCall replaces defaults; reference the
removeCall option and the ShakeVisitorConfig construction in napi.rs and
implement a merge (dedupe + prepend/append as desired) when building the config.
- Around line 171-173: The current should_remove_call only checks the local
callee name against target_calls, so aliased imports (local binding like `ue`
for `useEffect`) won't match; update the importer to record a mapping of local
binding id -> original imported name (e.g., import_map: HashMap<Id, String>) and
then change should_remove_call to: look up the callee's local Id
(fn_name.to_id()) in import_ids/import_map, and if present check
import_map.get(&id) (or the original name) against target_calls (fn_name.sym may
be the local alias, so use the mapped original name for comparison). Ensure the
mapping is populated where imports are collected and used in should_remove_call.
- Around line 199-203: The current transformation in visit_mut_expr replaces
removed calls with a plain identifier Expr::Ident(Ident::new("undefined"...)),
which can be shadowed by local bindings; change this to emit the expression void
0 instead. Locate visit_mut_expr (the branch matching Expr::Call and the call to
should_remove_call) and replace the Expr::Ident("undefined") construction with a
unary void expression (Unary op Void with numeric 0 as the argument) so the
replacement is immune to shadowing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6c20a263-f516-4b44-9963-e290dc7ca860

📥 Commits

Reviewing files that changed from the base of the PR and between 8f20056 and d6d1899.

📒 Files selected for processing (12)
  • .changeset/feat-react-transform-remove-call.md
  • packages/react/transform/crates/swc_plugin_shake/lib.rs
  • packages/react/transform/crates/swc_plugin_shake/napi.rs
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_not_remove_call_in_scope_id.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_remove_use_effect_call.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_remove_use_effect_param.js
  • packages/react/transform/crates/swc_plugin_shake/tests/__swc_snapshots__/lib.rs/should_replace_use_effect_call_with_undefined.js
  • packages/react/transform/index.d.ts
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • packages/rspeedy/plugin-react/etc/react-rsbuild-plugin.api.md
  • packages/webpack/react-refresh-webpack-plugin/package.json
  • packages/webpack/react-webpack-plugin/src/loaders/options.ts
✅ Files skipped from review due to trivial changes (6)
  • packages/react/transform/crates/swc_plugin_shake/tests/swc_snapshots/lib.rs/should_replace_use_effect_call_with_undefined.js
  • packages/react/transform/crates/swc_plugin_shake/tests/swc_snapshots/lib.rs/should_remove_use_effect_param.js
  • packages/react/transform/crates/swc_plugin_shake/tests/swc_snapshots/lib.rs/should_not_remove_call_in_scope_id.js
  • packages/webpack/react-refresh-webpack-plugin/package.json
  • packages/react/transform/crates/swc_plugin_shake/tests/swc_snapshots/lib.rs/should_remove_use_effect_call.js
  • .changeset/feat-react-transform-remove-call.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/react/transform/swc-plugin-reactlynx/index.d.ts
  • packages/react/transform/crates/swc_plugin_shake/napi.rs

@HuJean HuJean enabled auto-merge (squash) April 7, 2026 12:24
@HuJean HuJean merged commit 1f4f117 into main Apr 7, 2026
75 of 80 checks passed
@HuJean HuJean deleted the feat-react-transform-remove-call branch April 7, 2026 13:03
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.

3 participants