Skip to content

Enhance tree-shaking analysis with bundle size reporting and formatting utilities#7045

Merged
PavelVanecek merged 2 commits into
mainfrom
more-treeshaking-details
Feb 27, 2026
Merged

Enhance tree-shaking analysis with bundle size reporting and formatting utilities#7045
PavelVanecek merged 2 commits into
mainfrom
more-treeshaking-details

Conversation

@PavelVanecek

@PavelVanecek PavelVanecek commented Feb 23, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Added a comprehensive bundle-size reporting view showing ES6 baseline, tree-shaken, minified, and gzip-compressed stages with human-readable sizes and reduction percentages.
  • Tests
    • Added tests validating multi-stage bundle reports and size-formatting/reduction calculations.
  • Chores
    • Added a minification tool dependency to support minified size measurements.

@codecov

codecov Bot commented Feb 23, 2026

Copy link
Copy Markdown

Bundle Report

Changes will decrease total bundle size by 2.16kB (-0.04%) ⬇️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
recharts/bundle-umd 540.83kB -2.16kB (-0.4%) ⬇️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-umd

Assets Changed:

Asset Name Size Change Total Size Change (%)
Recharts.js -2.16kB 540.83kB -0.4%

@codecov

codecov Bot commented Feb 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.19%. Comparing base (cc89523) to head (4467ca1).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7045   +/-   ##
=======================================
  Coverage   90.19%   90.19%           
=======================================
  Files         526      526           
  Lines       39628    39628           
  Branches     5438     5438           
=======================================
  Hits        35744    35744           
  Misses       3875     3875           
  Partials        9        9           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
Contributor

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

@PavelVanecek

Copy link
Copy Markdown
Collaborator Author

@copilot rebase on main and run npm install again to resolve the conflict

Copilot AI commented Feb 24, 2026

Copy link
Copy Markdown
Contributor

@PavelVanecek I've opened a new pull request, #7054, to work on those changes. Once the pull request is ready, I'll request review from you.

@coderabbitai

coderabbitai Bot commented Feb 24, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Added terser dependency and implemented a bundle-size reporting feature: new getBundleSizeReport API, helpers formatBundleSize/getReductionPercent, minification and gzip sizing, refactored chunk extraction, CLI prints a tabulated report, and tests covering the report and formatting utilities.

Changes

Cohort / File(s) Summary
Dependency Management
package.json
Added dependency terser@^5.46.0 for JS minification.
Bundle Size Reporting
scripts/treeshaking.ts
Added getBundleSizeReport, types BundleSizeStage/BundleSizeReport, helpers getCombinedChunkCode, getDirectorySizeInBytes, formatBundleSize, getReductionPercent; integrates terser minification, gzip sizing (zlib), error handling, and refactors chunk-code extraction; CLI now prints a tabulated report.
Tests
scripts/treeshaking.test.ts
Added tests for getBundleSizeReport, formatBundleSize, and getReductionPercent; validate stage ordering, sizes across ES6/tree-shaken/minified/gzip, formatted outputs, and reduction percentages.

Sequence Diagram(s)

sequenceDiagram
    participant Build as Build Process
    participant Treeshake as scripts/treeshaking.ts
    participant Terser as terser
    participant Zlib as zlib
    participant Console as Console/Reporter

    Build->>Treeshake: getBundleSizeReport(components)
    Treeshake->>Treeshake: assemble ES6 code (getCombinedChunkCode)
    Treeshake->>Treeshake: compute ES6 size (getDirectorySizeInBytes)
    Treeshake->>Treeshake: tree-shake -> produce tree-shaken code
    Treeshake->>Terser: minify tree-shaken code
    Terser-->>Treeshake: return minified code
    Treeshake->>Zlib: gzip minified code
    Zlib-->>Treeshake: return gzip size
    Treeshake->>Treeshake: format sizes & compute reductions
    Treeshake->>Console: console.table(report)
    Treeshake-->>Build: return BundleSizeReport
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is missing entirely, violating the repository's required template with sections for Description, Related Issue, Motivation, Testing, and Checklist. Add a comprehensive pull request description following the template, including motivation, testing approach, and relevant checklist items for the new feature.
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: introducing bundle size reporting and formatting utilities for tree-shaking analysis.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch more-treeshaking-details

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.

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
scripts/treeshaking.ts (1)

224-246: Defensively copy component arrays before returning report.

Line 224 currently reuses caller-provided array, so report.components can be mutated from outside via aliasing. Use a copy to keep report data stable.

Suggested patch
-export async function getBundleSizeReport(components: string | string[]): Promise<BundleSizeReport> {
-  const normalizedComponents = Array.isArray(components) ? components : [components];
+export async function getBundleSizeReport(components: string | string[]): Promise<BundleSizeReport> {
+  const normalizedComponents = Array.isArray(components) ? [...components] : [components];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/treeshaking.ts` around lines 224 - 246, The returned report currently
reuses the caller-provided array via normalizedComponents, allowing external
mutation of report.components; change the return to store a defensive shallow
copy (e.g., use Array.from(...) or [...normalizedComponents]) for the components
property so the report's components cannot be mutated via aliasing (update the
return object that currently sets components: normalizedComponents).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/treeshaking.ts`:
- Around line 224-246: The returned report currently reuses the caller-provided
array via normalizedComponents, allowing external mutation of report.components;
change the return to store a defensive shallow copy (e.g., use Array.from(...)
or [...normalizedComponents]) for the components property so the report's
components cannot be mutated via aliasing (update the return object that
currently sets components: normalizedComponents).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between faeffe1 and 51c2759.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json
  • scripts/treeshaking.test.ts
  • scripts/treeshaking.ts

@PavelVanecek
PavelVanecek force-pushed the more-treeshaking-details branch from 51c2759 to b15b38f Compare February 26, 2026 14:27

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (2)
scripts/treeshaking.ts (1)

361-370: Consider adding validation for empty component arguments.

If the script is called without any component arguments, getBundleSizeReport([]) will execute with an empty array. While this may technically work, adding a validation check would provide a better developer experience.

💡 Suggested validation
 if (require.main === module) {
   const components = process.argv.slice(2);
+  if (components.length === 0) {
+    console.error('Usage: npx tsx scripts/treeshaking.ts <ComponentName> [ComponentName...]');
+    process.exit(1);
+  }
   getBundleSizeReport(components)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/treeshaking.ts` around lines 361 - 370, The script's entry block (the
require.main === module section) calls getBundleSizeReport with components
derived from process.argv without validating them; add a guard that checks
components.length and if zero prints a helpful usage message (including expected
component names or an example), then exits with a non-zero code (or returns) to
avoid calling getBundleSizeReport([]). Keep this validation adjacent to the
components declaration and before invoking getBundleSizeReport so the flow uses
the new check to short-circuit invalid invocation.
scripts/treeshaking.test.ts (1)

116-127: Consider adding edge case test for negative reduction.

The tests cover the happy path well. However, getReductionPercent could return negative values when reducedSizeInBytes > baselineSizeInBytes. Consider adding a test to document this behavior if it's expected, or the implementation should handle it.

💡 Suggested additional test case
   it('calculates reduction percentage', () => {
     expect(getReductionPercent(1000, 650)).toBe(35);
     expect(getReductionPercent(0, 100)).toBe(0);
+    // Document behavior when reduced > baseline (negative reduction)
+    expect(getReductionPercent(100, 150)).toBe(-50);
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/treeshaking.test.ts` around lines 116 - 127, Add an edge-case test
for getReductionPercent in scripts/treeshaking.test.ts that verifies behavior
when reducedSizeInBytes > baselineSizeInBytes (e.g., baseline 100, reduced 150)
so the test either asserts the function returns a negative percent (documenting
current behavior) or, if you prefer non-negative output, update the
getReductionPercent implementation to clamp negative results to 0 and then
assert 0 in the new test; reference getReductionPercent in your changes and keep
the test grouped with the existing "calculates reduction percentage" cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/treeshaking.test.ts`:
- Around line 116-127: Add an edge-case test for getReductionPercent in
scripts/treeshaking.test.ts that verifies behavior when reducedSizeInBytes >
baselineSizeInBytes (e.g., baseline 100, reduced 150) so the test either asserts
the function returns a negative percent (documenting current behavior) or, if
you prefer non-negative output, update the getReductionPercent implementation to
clamp negative results to 0 and then assert 0 in the new test; reference
getReductionPercent in your changes and keep the test grouped with the existing
"calculates reduction percentage" cases.

In `@scripts/treeshaking.ts`:
- Around line 361-370: The script's entry block (the require.main === module
section) calls getBundleSizeReport with components derived from process.argv
without validating them; add a guard that checks components.length and if zero
prints a helpful usage message (including expected component names or an
example), then exits with a non-zero code (or returns) to avoid calling
getBundleSizeReport([]). Keep this validation adjacent to the components
declaration and before invoking getBundleSizeReport so the flow uses the new
check to short-circuit invalid invocation.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51c2759 and b15b38f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json
  • scripts/treeshaking.test.ts
  • scripts/treeshaking.ts

@github-actions

Copy link
Copy Markdown
Contributor

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

@PavelVanecek
PavelVanecek force-pushed the more-treeshaking-details branch from b15b38f to 4467ca1 Compare February 27, 2026 12:04

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
scripts/treeshaking.test.ts (1)

93-113: Consider adding assertion for minified.bytes <= treeShaken.bytes.

The test validates that minified.bytes <= es6Folder.bytes but could also verify the tighter invariant that minified size is at most the tree-shaken size, similar to how minifiedGzip.bytes <= minified.bytes is checked.

♻️ Suggested additional assertion
     expect(minified.bytes).toBeLessThanOrEqual(es6Folder.bytes);
+    expect(minified.bytes).toBeLessThanOrEqual(treeShaken.bytes);
     expect(minifiedGzip.bytes).toBeLessThanOrEqual(minified.bytes);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/treeshaking.test.ts` around lines 93 - 113, Add an assertion to
enforce the tighter invariant that the minified stage is no larger than the
tree-shaken stage in the test "returns bundle size report with es6 baseline,
tree-shaken, minified and gzip stages": after destructuring the stages into
es6Folder, treeShaken, minified, minifiedGzip (and alongside the other size
comparisons), add expect(minified.bytes).toBeLessThanOrEqual(treeShaken.bytes);
so the test verifies minified <= tree-shaken in addition to the existing
comparisons.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/treeshaking.test.ts`:
- Around line 93-113: Add an assertion to enforce the tighter invariant that the
minified stage is no larger than the tree-shaken stage in the test "returns
bundle size report with es6 baseline, tree-shaken, minified and gzip stages":
after destructuring the stages into es6Folder, treeShaken, minified,
minifiedGzip (and alongside the other size comparisons), add
expect(minified.bytes).toBeLessThanOrEqual(treeShaken.bytes); so the test
verifies minified <= tree-shaken in addition to the existing comparisons.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b15b38f and 4467ca1.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json
  • scripts/treeshaking.test.ts
  • scripts/treeshaking.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

@github-actions

Copy link
Copy Markdown
Contributor

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

@PavelVanecek

Copy link
Copy Markdown
Collaborator Author

The missing errorbars are already on main

@PavelVanecek
PavelVanecek merged commit d6ab58e into main Feb 27, 2026
48 of 49 checks passed
@PavelVanecek
PavelVanecek deleted the more-treeshaking-details branch February 27, 2026 12:50
@coderabbitai coderabbitai Bot mentioned this pull request Mar 1, 2026
7 tasks
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.

3 participants