chore(examples): add bundle analysis and blocking size budgets - #1145
chore(examples): add bundle analysis and blocking size budgets#1145redfish4ktc wants to merge 4 commits into
Conversation
Every bundled example can now inspect what ends up in its bundle: Rsdoctor for the webpack ones, vite-bundle-analyzer for the Vite ones. Both are opt-in through 'npm run build:analyze' and never affect the regular build. The production build now fails when a bundle grows, with webpack 'performance' budgets and, for Vite, a shared plugin, since chunkSizeWarningLimit only logs a warning and lets the build succeed. Each limit is the smallest value that passes, the current size rounded up to the next kB, so the budgets track the size evolution. The convention is recorded in .claude/rules/tooling/bundle-size-budgets.md. scripts/build-all-examples.bash gains --fail-at-end, used by the CI: a single run shows every example, the size table, then the failures. Dependabot groups the vite and the rsdoctor updates, so those libraries stay consistent across the examples.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (6)
Included review availability: Your plan includes up to 4 reviews per rolling hour; 3 remain after this review. WalkthroughChangesThe example packages now support production bundle analysis with Rsdoctor or Bundle analysis and size enforcement
Estimated code review effort: 4 (Complex) | ~45 minutes Merge Risk: ⚪ Minimal · up to This PR adds opt-in bundle analysis and production size-budget enforcement without changing regular build output; no actionable merge-blocking risk remains. Sequence Diagram(s)sequenceDiagram
participant BuildExamples
participant ExampleBuild
participant SizeGuard
participant ArtifactUpload
BuildExamples->>ExampleBuild: build each example with --fail-at-end
ExampleBuild->>SizeGuard: enforce Webpack or Vite budget
SizeGuard-->>ExampleBuild: success or size-limit failure
ExampleBuild-->>BuildExamples: record example result
BuildExamples->>ArtifactUpload: upload completed artifacts unless cancelled
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: f189e624-c711-4fb2-9850-e68842af414d
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (25)
.claude/rules/tooling/bundle-size-budgets.md.github/dependabot.yml.github/workflows/_reusable_build_examples.ymlCLAUDE.mdpackages/js-example-selected-features/README.mdpackages/js-example-selected-features/package.jsonpackages/js-example-selected-features/webpack.config.jspackages/js-example-without-defaults/README.mdpackages/js-example-without-defaults/package.jsonpackages/js-example-without-defaults/webpack.config.jspackages/js-example/README.mdpackages/js-example/package.jsonpackages/js-example/webpack.config.jspackages/ts-example-selected-features/README.mdpackages/ts-example-selected-features/package.jsonpackages/ts-example-selected-features/vite.config.jspackages/ts-example-without-defaults/README.mdpackages/ts-example-without-defaults/package.jsonpackages/ts-example-without-defaults/vite.config.jspackages/ts-example/README.mdpackages/ts-example/package.jsonpackages/ts-example/vite.config.jsscripts/build-all-examples.bashscripts/vite/chunk-size-limit.mjsscripts/vite/maxgraph-chunk.mjs
Included review availability: Your plan includes up to 4 reviews per rolling hour; 3 remain after this review.
… runs 'build:analyze' builds in production mode, so the performance hints stayed set to 'error' and an oversized bundle made the compilation report a size error during a run whose only purpose is to explain that very size. The report itself was never lost, Rsdoctor still wrote its payload and served it, but the run reported a failure and would have exited non-zero without the report server holding the process open. The Vite examples already skip their guard when analyzing, so this also aligns the two bundlers. 'npm run build', which the CI runs, remains the command that enforces the budget. Verified with a budget forced down to 10 kB: the analyze run now reports no size error and still serves its report, while the plain build still exits 1.
The ESLint configuration declares no Node environment for the JavaScript configuration files, so 'process.env.ANALYZE' was reported as no-undef. Importing process from 'node:process' makes the dependency explicit, which is also what the shared chunk size plugin does for Buffer. Note that 'npm run lint' only covers '**/*.ts', so these files are outside its scope and the error only surfaces in tooling that lints them directly.
|


Why
The bundled example packages had no way to tell what ends up in their bundle, and no guard against it growing.
The Vite examples declared a
chunkSizeWarningLimit, but it only makes Vite log a warning and the build still exits 0, so a bundle regression showed up as a single line in a CI log that nobody reads (upstream request: vitejs/vite#18496). The webpack examples had no budget at all.What
Bundle analysis, opt-in, in the six bundled examples. Rsdoctor for the three webpack examples, vite-bundle-analyzer for the three Vite ones, since Rsdoctor supports only webpack and Rspack. Both are enabled by a dedicated
npm run build:analyzescript, which setsANALYZE=truethroughcross-envso the command also works in Windows shells. The regularnpm run buildis untouched: no analyzer, no report server, no source map. A source map is generated for the analyze run only,hidden-source-mapfor webpack andsourcemap: 'hidden'for Vite, so the analyzed bundle stays byte for byte the one the regular build produces, content hash included; Rsdoctor needs it to attribute bytes to individual modules.The production build now fails when a bundle grows. The webpack examples get a
performancebudget withhints: 'error', in production only, since development bundles are not minified and would breaknpm run dev. Vite cannot do this on its own, so the examples pass their limit to a shared plugin,scripts/vite/chunk-size-limit.mjs, which fails the build naming the chunk and both sizes. Each limit is declared once per example and feeds bothchunkSizeWarningLimitand the plugin, so the warning and the error cannot drift apart.Each value is the smallest one that passes, that is the current size rounded up to the next kB. The intent is to follow the size evolution rather than to leave room to grow into, so the incidental headroom is accepted; the convention is recorded in
.claude/rules/tooling/bundle-size-budgets.md.--fail-at-endinscripts/build-all-examples.bash, used by the CI. Once a build can fail on size, the first failure would abort the script and hide both the other examples and the size table, so getting the full picture would take one CI run per failing example. With the option, every example is built, the file listing, the markdown table and the CSV are still printed, and the failures are reported after them. The default behavior is unchanged: without the option the script still stops at the first failing build.Shared Vite configuration. The
codeSplittinggroup that isolates@maxgraph/corein a dedicatedmaxgraphchunk was copy pasted in the three Vite examples; it now lives inscripts/vite/maxgraph-chunk.mjsnext to the size check it feeds. The threevite.config.jsare identical apart from their limit, and the threewebpack.config.jsapart from their budget.Dependabot. New
vitegroup forviteandvite-*, and@rsdoctor/*added to the existingwebpackgroup, so those libraries move together across the examples.@storybook/html-viteis deliberately left in thestorybookgroup, which owns the Vite version Storybook builds against.Sizes and budgets
No bundle size changed in this PR. The
js-example-without-defaultsbudget was initially calibrated against a stalepackages/core/lib; rebuilding core brings that bundle to 239,112 B, and the budget follows.Decisions worth flagging
vite-bundle-analyzeris a post plugin, so the guard's error aborted the build before any report was written, exactly the case where the report is needed to find out what grew.npm run build, which the CI runs, remains the command that enforces the limit.--list-size-only --fail-at-endis a documented no-op, not an error: nothing is built, so nothing can fail, and a caller passing flags generically should not be rejected for a harmless combination.if: ${{ !cancelled() }}. Skipping it on failure would defeat the purpose of--fail-at-end, since thedistof the examples that did build is what one wants to inspect. This does not weaken the gate: the job still fails, so the jobs depending on it, the release included, do not run.dist, so a failing example disappears from the size table and the CSV instead of showing a stale number.Validation
./scripts/build-all-examples.bashand./scripts/build-all-examples.bash --fail-at-end: exit 0, the six examples below their limits, no webpack performance warning and no Vite chunk warning.RolldownError: Chunk "assets/maxgraph-Be5ReXNy.js" is 361.55 kB, above the 10 kB limit.and exit 1.--fail-at-endproven: with two limits lowered, both failures are listed after the size table, the third example still builds, exit code 1.npm run lintclean. Note it only covers**/*.ts, so the two new.mjsfiles are outside its scope; they were linted explicitly.Summary by CodeRabbit
New Features
maxgraphbundle generation.Documentation
Chores