Skip to content

feat: align tree shaking behavior with webpack - #15397

Closed
LingyuCoder wants to merge 5 commits into
mainfrom
seal/tree-shaking-bundler-audit
Closed

feat: align tree shaking behavior with webpack#15397
LingyuCoder wants to merge 5 commits into
mainfrom
seal/tree-shaking-bundler-audit

Conversation

@LingyuCoder

Copy link
Copy Markdown
Contributor

Summary

  • align CommonJS tree shaking with webpack, including object-literal exports, deep reexports, member access, Object.defineProperty reexports, unused side-effect-free require() calls, and exported-function this handling
  • extend inner-graph purity analysis for cross-module imports, nested export paths, object/array/template expressions, configured pure functions, and precise NO_SIDE_EFFECTS annotations
  • align nested package sideEffects resolution, glob rebasing, symlink handling, and star-reexport graph reconnect behavior
  • add webpack-compatible output.environment.spread target/default/runtime handling and port the corresponding regression fixtures

Related links

Validation

  • pnpm run test:unit (Rspack: 9280 passed, 4 skipped; CLI: 90 passed, 1 skipped; binding type tests passed)
  • cargo clippy --workspace --all-targets --tests --locked -- -D warnings
  • pnpm run format:rs
  • pnpm run format:js
  • cargo fmt --all --check
  • git diff --check

Checklist

  • Tests updated (or not required).
  • Documentation updated (not required; no stable user-facing API behavior is documented by this change).

@LingyuCoder
LingyuCoder requested a review from hardfist as a code owner August 30, 2026 07:25
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-30T12:07:00.074725Z 7a941e4 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea717e5bef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

📦 Binary Size-limit

Comparing 7a941e4 to perf(ids): optimize deterministic module id assignment (#15393) by harpsealjs

❌ Size increased by 108.13KB from 68.30MB to 68.40MB (⬆️0.15%)

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Rsdoctor Bundle Diff Analysis

⚠️ Note: The latest commit (e434f1fe9e) does not have baseline artifacts. Using commit f281cc9f99 for baseline comparison instead. If this seems incorrect, please wait a few minutes and try rerunning the workflow.

Found 5 projects in monorepo, 5 projects with changes.

📊 Quick Summary
Project Total Size Gzip Size Change Gzip Change
popular-libs 1.7 MB 555.2 KB -3.1 KB (-0.2%) -1.3 KB (-0.2%)
react-10k 5.6 MB 1.3 MB -26.0 B (-0.0%) -3.0 B (-0.0%)
react-1k 823.0 KB 218.4 KB -26.0 B (-0.0%) -3.0 B (-0.0%)
react-5k 2.7 MB 669.3 KB -26.0 B (-0.0%) -3.0 B (-0.0%)
ui-components 4.9 MB 1.4 MB -97.0 B (-0.0%) -24.0 B (-0.0%)
📋 Detailed Reports (Click to expand)

📁 popular-libs

Path: ../build-tools-performance/cases/popular-libs/dist/rsdoctor-data.json

📌 Baseline Commit: f281cc9f99 | PR: #15393

Metric Current Baseline Change
📊 Total Size 1.7 MB 1.7 MB -3.1 KB (-0.2%)
🗜️ Gzip Size 555.2 KB 556.5 KB -1.3 KB (-0.2%)
📄 JavaScript 1.7 MB 1.7 MB -3.1 KB (-0.2%)
🎨 CSS 0 B 0 B 0
🌐 HTML 289.0 B 289.0 B 0
📁 Other Assets 0 B 0 B 0

📦 Download Diff Report: popular-libs Bundle Diff

📁 react-10k

Path: ../build-tools-performance/cases/react-10k/dist/rsdoctor-data.json

📌 Baseline Commit: f281cc9f99 | PR: #15393

Metric Current Baseline Change
📊 Total Size 5.6 MB 5.6 MB -26.0 B (-0.0%)
🗜️ Gzip Size 1.3 MB 1.3 MB -3.0 B (-0.0%)
📄 JavaScript 5.6 MB 5.6 MB -26.0 B (-0.0%)
🎨 CSS 21.0 B 21.0 B 0
🌐 HTML 328.0 B 328.0 B 0
📁 Other Assets 0 B 0 B 0

📦 Download Diff Report: react-10k Bundle Diff

📁 react-1k

Path: ../build-tools-performance/cases/react-1k/dist/rsdoctor-data.json

📌 Baseline Commit: f281cc9f99 | PR: #15393

Metric Current Baseline Change
📊 Total Size 823.0 KB 823.1 KB -26.0 B (-0.0%)
🗜️ Gzip Size 218.4 KB 218.4 KB -3.0 B (-0.0%)
📄 JavaScript 822.7 KB 822.7 KB -26.0 B (-0.0%)
🎨 CSS 0 B 0 B 0
🌐 HTML 328.0 B 328.0 B 0
📁 Other Assets 0 B 0 B 0

📦 Download Diff Report: react-1k Bundle Diff

📁 react-5k

Path: ../build-tools-performance/cases/react-5k/dist/rsdoctor-data.json

📌 Baseline Commit: f281cc9f99 | PR: #15393

Metric Current Baseline Change
📊 Total Size 2.7 MB 2.7 MB -26.0 B (-0.0%)
🗜️ Gzip Size 669.3 KB 669.3 KB -3.0 B (-0.0%)
📄 JavaScript 2.7 MB 2.7 MB -26.0 B (-0.0%)
🎨 CSS 21.0 B 21.0 B 0
🌐 HTML 328.0 B 328.0 B 0
📁 Other Assets 0 B 0 B 0

📦 Download Diff Report: react-5k Bundle Diff

📁 ui-components

Path: ../build-tools-performance/cases/ui-components/dist/rsdoctor-data.json

📌 Baseline Commit: f281cc9f99 | PR: #15393

Metric Current Baseline Change
📊 Total Size 4.9 MB 4.9 MB -97.0 B (-0.0%)
🗜️ Gzip Size 1.4 MB 1.4 MB -24.0 B (-0.0%)
📄 JavaScript 4.8 MB 4.8 MB -97.0 B (-0.0%)
🎨 CSS 112.5 KB 112.5 KB 0
🌐 HTML 328.0 B 328.0 B 0
📁 Other Assets 0 B 0 B 0

📦 Download Diff Report: ui-components Bundle Diff

🤖 AI Degradation Analysis (Click to expand)

📁 popular-libs

📊 Size Changes

Asset / Chunk Baseline Current Δ Size Δ % Initial?
No significant regressions detected 🎉

🔍 Root Cause Analysis

  • react-i18next Optimization: Package parsed size dropped 20.1% (14,593 → 11,660 bytes).
  • Tree-shaking: Unused ICU modules (e.g., IcuTrans.js, htmlEntityDecoder.js) successfully eliminated from the bundle.

⚠️ Risk Assessment

Overall severity: Low

  • Total bundle size decreased by 3,219 bytes (-0.18%), improving initial load performance with no regressions.

💡 Optimization Suggestions

  1. Validate ICU message formatting in-app to ensure tree-shaken modules weren't required.
  2. Monitor html-parse-stringify (parsed size +4 bytes) for future accumulation.

Analysis by qwen3.5-plus

📁 react-10k

📊 Size Changes

No significant regressions detected 🎉

🔍 Root Cause Analysis

  • Total Bundle: Decreased by 26 bytes (5,861,069 → 5,861,043).
  • react-router: v7.18.2 parsed size reduced slightly (35,481 → 35,455 bytes), driving the total delta.
  • No new modules or duplicate dependencies detected.

⚠️ Risk Assessment

Overall severity: Low

  • Initial JS chunk decreased by 26 bytes (746,165 → 746,139); zero negative impact on TTI or FCP expected.

💡 Optimization Suggestions

  1. Merge Safely: No performance regressions identified; PR is safe to land.
  2. Monitor: Continue observing react-router usage if upgrading to newer majors later.

Analysis by qwen3.5-plus

📁 react-1k

📊 Size Changes

No meaningful change detected. Total bundle size decreased slightly from 842,817 B to 842,791 B (-26 B). No significant regressions detected 🎉.

🔍 Root Cause Analysis

  • No new modules added or removed.
  • react-router (v7.18.2) parsedSize decreased negligibly (35,481 B → 35,455 B).
  • Build variance likely accounts for the minor delta.

⚠️ Risk Assessment

Overall severity: Low

  • Initial chunk size decreased by 26 B (776,474 B → 776,448 B); no impact on load performance.

💡 Optimization Suggestions

  1. No action required; bundle stability is maintained.
  2. Continue monitoring react-router usage as the app scales.

Analysis by qwen3.5-plus

📁 react-5k

📊 Size Changes

No significant regressions detected 🎉.

🔍 Root Cause Analysis

  • Negligible size reduction driven by react-router parsed size change (35,481 → 35,455 bytes).
  • No new dependencies or modules introduced; asset count remains stable at 18.

⚠️ Risk Assessment

Overall severity: Low
Total bundle size decreased (2,793,975 → 2,793,949 bytes) and initial chunk remained stable (525,536 → 525,510 bytes), ensuring no load performance impact.

💡 Optimization Suggestions

  1. Safe to merge; no optimization needed.
  2. Maintain current code-splitting strategy for future updates.

Analysis by qwen3.5-plus

📁 ui-components

📊 Size Changes

No significant regressions detected 🎉.

🔍 Root Cause Analysis

  • Total bundle size decreased by 97 bytes (5,138,933 → 5,138,836).
  • @vueuse/core parsedSize reduced by 97 bytes (3,132 → 3,035), indicating improved tree-shaking.
  • Two date-fns-tz modules (fromZonedTime, getTimezoneOffset) were removed from the bundle.

⚠️ Risk Assessment

Overall severity: Low

  • Initial chunk size decreased negligibly (~0.002%); no impact on load performance or user experience.

💡 Optimization Suggestions

  1. Verify Removals: Confirm date-fns-tz functions were removed intentionally and not due to broken imports.
  2. Monitor VueUse: Continue importing specific @vueuse/core functions rather than the whole library to maintain small parsedSize.
  3. Maintain Config: Current Rspack tree-shaking configuration is effective; no immediate changes required.

Analysis by qwen3.5-plus

Generated by Rsdoctor GitHub Action

@codspeed-hq

codspeed-hq Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will degrade performance by 3.04%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 5 regressed benchmarks
✅ 45 untouched benchmarks
⏩ 47 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation rust@create_chunk_hashes 1.6 ms 1.7 ms -4.7%
Simulation rust@scan_dependencies@three_module 12.9 ms 13.3 ms -3.39%
Simulation bundle@misc-production-sourcemap 3.6 s 3.7 s -2.53%
Simulation bundle@misc-development 2.8 s 2.8 s -2.5%
Simulation rust@create_full_hash 2.3 ms 2.3 ms -2.07%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing seal/tree-shaking-bundler-audit (7a941e4) with main (f281cc9)2

Open in CodSpeed

Footnotes

  1. 47 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.

  2. No successful run was found on main (e434f1f) during the generation of this report, so f281cc9 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5be836198b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/rspack_plugin_javascript/src/parser_plugin/side_effects_parser_plugin.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

if is_side_effects_free_function_body(
parser,
analyze_side_effects_free,
&fn_decl.function,
comments,
) {
mark_side_effects_free(parser, &ident, None);

P1 Badge Exclude reassigned declarations from automatic purity

In production configurations where automatic pure-function analysis is enabled, this new path marks a function declaration as side-effect-free without consulting the written set used by the annotation pass. Thus function f() {}; f = () => effect(); export const unused = f(); still classifies the final call as pure and can remove effect(). Apply the same write invalidation to automatically inferred function declarations, including exported declarations.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@LingyuCoder

Copy link
Copy Markdown
Contributor Author

Addressed the additional review-summary finding in 7a941e4: automatic purity inference now excludes top-level function bindings recorded as written, including exported function declarations. I also added regression coverage for ordinary and exported declarations reassigned to effectful functions.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a941e4095

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1076 to +1078
} else if analyze_side_effects_free
&& let Some(callee_expr) = callee.as_expr()
&& let Some(imported_callee) = imported_pure_callee(parser, callee_expr)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve namespace reads across cyclic module initialization

When a namespace member call participates in a cycle, treating it as removable based only on the target function's purity can suppress a required TDZ error. For example, if entry module B imports A before initializing export const f = () => 1, while A evaluates import * as ns from "./b"; export const unused = ns.f();, ns.f must throw because f is still uninitialized; this new branch defers only the function-purity check and can remove the entire call when unused is unused. Keep namespace/member accesses observable unless the import is known to have completed initialization.

Useful? React with 👍 / 👎.

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.

1 participant