-
-
Notifications
You must be signed in to change notification settings - Fork 637
Add bundle size CI check using size-limit #2149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
34f5412
a422fe6
fd56f7a
f727385
7cf319d
d26de94
25f3766
451924c
dbb3907
4ba4dff
a122bb9
8d48b13
527b8fb
afcbf70
b1c46b8
0b5fea6
fc592d6
277fea8
89fc846
cc0c564
8374d77
58e158c
818a710
90b84c7
fe55a99
7468b45
4bcadfc
40fd2fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # This file allows skipping the bundle size CI check for a specific branch. | ||
| # When a branch name in this file matches the PR branch, the size check is skipped. | ||
| # | ||
| # Usage: Run `bin/skip-bundle-size-check` to set the current branch, then commit and push. | ||
| # | ||
| # This is useful when you have an intentional size increase that exceeds the 0.5KB threshold. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| name: Bundle Size | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - 'packages/**' | ||
| - 'package.json' | ||
| - 'pnpm-lock.yaml' | ||
| - '.size-limit.json' | ||
| - '.github/workflows/bundle-size.yml' | ||
| - '.bundle-size-skip-branch' | ||
|
|
||
| jobs: | ||
| check-skip: | ||
| runs-on: ubuntu-22.04 | ||
| outputs: | ||
| skip: ${{ steps.skip-check.outputs.skip }} | ||
| steps: | ||
| - name: Checkout PR branch | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Check if branch should skip size check | ||
| id: skip-check | ||
| env: | ||
| BRANCH: ${{ github.head_ref }} | ||
| run: | | ||
| SKIP_FILE=".bundle-size-skip-branch" | ||
| SKIP_BRANCH=$(grep -v '^[[:space:]]*#' "$SKIP_FILE" 2>/dev/null | grep -v '^[[:space:]]*$' | tr -d '[:space:]' || echo "") | ||
| if [ "$SKIP_BRANCH" = "$BRANCH" ]; then | ||
| echo "skip=true" >> $GITHUB_OUTPUT | ||
| echo "::notice::Branch '$BRANCH' is set to skip size check" | ||
| else | ||
| echo "skip=false" >> $GITHUB_OUTPUT | ||
| fi | ||
| size: | ||
| needs: check-skip | ||
| if: needs.check-skip.outputs.skip != 'true' | ||
| runs-on: ubuntu-22.04 | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| env: | ||
| CI_JOB_NUMBER: 1 | ||
| steps: | ||
| - name: Setup Node | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22' | ||
|
|
||
| - name: Setup pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: 9 | ||
|
|
||
| # 1. Get PR's size-limit config first (base branch may not have it) | ||
| - name: Checkout PR branch for config | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Save size-limit config | ||
| run: cp .size-limit.json /tmp/size-limit-config.json | ||
|
|
||
| # 2. Get base branch sizes | ||
| - name: Checkout base branch | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.base_ref }} | ||
|
|
||
| - name: Copy size-limit config to base branch | ||
| run: cp /tmp/size-limit-config.json .size-limit.json | ||
|
|
||
| - name: Install base dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Build base branch | ||
| run: pnpm run build | ||
|
|
||
| - name: Verify build artifacts | ||
| run: | | ||
| missing=0 | ||
| for pkg in react-on-rails react-on-rails-pro react-on-rails-pro-node-renderer; do | ||
| if ! ls packages/$pkg/lib/*.js >/dev/null 2>&1; then | ||
| echo "::error::Missing build artifacts in packages/$pkg/lib/" | ||
| missing=1 | ||
| fi | ||
| done | ||
| if [ $missing -eq 1 ]; then | ||
| exit 1 | ||
| fi | ||
| echo "All build artifacts verified" | ||
| - name: Measure base branch sizes | ||
| run: | | ||
| pnpm exec size-limit --json > /tmp/base-sizes.json | ||
| echo "Base branch sizes:" | ||
| cat /tmp/base-sizes.json | ||
| # 3. Checkout PR and set dynamic limits | ||
| - name: Checkout PR branch | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install PR dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Set dynamic limits (base + 0.5KB) | ||
| run: node scripts/bundle-size.mjs set-limits --base /tmp/base-sizes.json | ||
|
|
||
| # 4. Run the action with dynamic limits | ||
| - name: Check bundle size | ||
| uses: andresz1/size-limit-action@v1 | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| package_manager: pnpm | ||
| build_script: build | ||
| skip_step: install | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -305,6 +305,69 @@ Run only ESLint: | |
| pnpm run lint | ||
| ``` | ||
|
|
||
| ### Bundle Size Checks | ||
|
|
||
| React on Rails monitors bundle sizes in CI to prevent unexpected size increases. The CI compares your PR's bundle sizes against the base branch and fails if any package increases by more than 0.5KB. | ||
|
|
||
| #### Running Locally | ||
|
|
||
| Check current bundle sizes: | ||
|
|
||
| ```sh | ||
| pnpm run size | ||
| ``` | ||
|
|
||
| Get JSON output for programmatic use: | ||
|
|
||
| ```sh | ||
| pnpm run size:json | ||
| ``` | ||
|
|
||
| Compare your branch against the base branch: | ||
|
|
||
| ```sh | ||
| bin/compare-bundle-sizes | ||
| ``` | ||
|
|
||
| This script automatically: | ||
|
|
||
| 1. Stashes any uncommitted changes | ||
| 2. Checks out and builds the base branch (default: `master`) | ||
| 3. Checks out and builds your current branch | ||
| 4. Compares the sizes and shows a detailed report | ||
|
|
||
| Options: | ||
|
|
||
| ```sh | ||
| bin/compare-bundle-sizes main # Compare against 'main' instead of 'master' | ||
| bin/compare-bundle-sizes --hierarchical # Group results by package | ||
| ``` | ||
|
Comment on lines
+343
to
+344
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The The Options:
```sh
bin/compare-bundle-sizes main # Compare against 'main' instead of 'master'
-bin/compare-bundle-sizes --hierarchical # Group results by packageIn CONTRIBUTING.md around lines 343-344 the docs mention a --hierarchical flag |
||
|
|
||
| #### Bypassing the Check | ||
|
|
||
| If your PR intentionally increases bundle size (e.g., adding a new feature), you can skip the bundle size check: | ||
|
|
||
| ```sh | ||
| # Run from your PR branch | ||
| bin/skip-bundle-size-check | ||
| git add .bundle-size-skip-branch | ||
| git commit -m "Skip bundle size check for intentional size increase" | ||
| git push | ||
| ``` | ||
|
|
||
| This sets your branch to skip the size check. The skip only applies to the specific branch name written to `.bundle-size-skip-branch`. | ||
|
|
||
| **Important**: Only skip the check when the size increase is justified. Document why the increase is acceptable in your PR description. | ||
|
|
||
| #### What Gets Measured | ||
|
|
||
| The CI measures sizes for: | ||
|
|
||
| - **react-on-rails**: Raw, gzip, and brotli compressed sizes | ||
| - **react-on-rails-pro**: Raw, gzip, and brotli compressed sizes | ||
| - **react-on-rails-pro-node-renderer**: Raw, gzip, and brotli compressed sizes | ||
| - **Webpack bundled imports**: Client-side bundle sizes when importing via webpack | ||
|
|
||
| ### Starting the Dummy App | ||
|
|
||
| To run the dummy app, it's **CRITICAL** to not just run `rails s`. You have to run `foreman start` with one of the Procfiles. If you don't do this, then `webpack` will not generate a new bundle, and you will be seriously confused when you change JavaScript and the app does not change. If you change the Webpack configs, then you need to restart Foreman. If you change the JS code for react-on-rails, you need to run `pnpm run build` in the project root. | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,69 @@ | ||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||
| # | ||||||||||||||
| # Compare bundle sizes between current branch and a base branch | ||||||||||||||
| # | ||||||||||||||
| # Usage: | ||||||||||||||
| # bin/compare-bundle-sizes [base-branch] | ||||||||||||||
| # | ||||||||||||||
| # Arguments: | ||||||||||||||
| # base-branch The branch to compare against (default: master) | ||||||||||||||
| # | ||||||||||||||
| # Examples: | ||||||||||||||
| # bin/compare-bundle-sizes # Compare against master | ||||||||||||||
| # bin/compare-bundle-sizes develop # Compare against develop | ||||||||||||||
| # bin/compare-bundle-sizes feature/some-branch | ||||||||||||||
|
|
||||||||||||||
| set -e | ||||||||||||||
|
|
||||||||||||||
| BASE_BRANCH="${1:-master}" | ||||||||||||||
| CURRENT_BRANCH=$(git branch --show-current) | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Detached HEAD state may cause issues in CI environments.
Consider adding a fallback to use the commit SHA: -CURRENT_BRANCH=$(git branch --show-current)
+CURRENT_BRANCH=$(git branch --show-current)
+if [ -z "$CURRENT_BRANCH" ]; then
+ # Fallback to commit SHA for detached HEAD (common in CI)
+ CURRENT_BRANCH=$(git rev-parse HEAD)
+fi📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| STASHED=false | ||||||||||||||
|
|
||||||||||||||
| # Colors for output | ||||||||||||||
| YELLOW='\033[1;33m' | ||||||||||||||
| BLUE='\033[0;34m' | ||||||||||||||
| NC='\033[0m' # No Color | ||||||||||||||
|
|
||||||||||||||
| cleanup() { | ||||||||||||||
| echo -e "\n${BLUE}Cleaning up...${NC}" | ||||||||||||||
| git checkout "$CURRENT_BRANCH" --quiet 2>/dev/null || true | ||||||||||||||
| if [ "$STASHED" = true ]; then | ||||||||||||||
| git stash pop --quiet 2>/dev/null || true | ||||||||||||||
| fi | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| trap cleanup EXIT | ||||||||||||||
|
|
||||||||||||||
| echo -e "${BLUE}📦 Bundle Size Comparison${NC}" | ||||||||||||||
| echo -e " Current branch: ${YELLOW}$CURRENT_BRANCH${NC}" | ||||||||||||||
| echo -e " Base branch: ${YELLOW}$BASE_BRANCH${NC}" | ||||||||||||||
| echo "" | ||||||||||||||
|
|
||||||||||||||
| # Check for uncommitted changes | ||||||||||||||
| if ! git diff --quiet || ! git diff --cached --quiet; then | ||||||||||||||
| echo -e "${YELLOW}Stashing uncommitted changes...${NC}" | ||||||||||||||
| git stash push -m "compare-bundle-sizes temp stash" --quiet | ||||||||||||||
| STASHED=true | ||||||||||||||
| fi | ||||||||||||||
|
|
||||||||||||||
| # Get base branch sizes | ||||||||||||||
| echo -e "${BLUE}Building base branch ($BASE_BRANCH)...${NC}" | ||||||||||||||
| git fetch origin "$BASE_BRANCH" --quiet 2>/dev/null || true | ||||||||||||||
| git checkout "$BASE_BRANCH" --quiet 2>/dev/null || git checkout "origin/$BASE_BRANCH" --quiet | ||||||||||||||
| pnpm install --frozen-lockfile 2>&1 | grep -v "^$" | head -5 || true | ||||||||||||||
| pnpm run build 2>&1 | grep -v "^$" | tail -3 || true | ||||||||||||||
|
|
||||||||||||||
| echo -e "${BLUE}Measuring base branch sizes...${NC}" | ||||||||||||||
| pnpm exec size-limit --json > /tmp/base-sizes.json | ||||||||||||||
|
|
||||||||||||||
| # Get current branch sizes | ||||||||||||||
| echo -e "${BLUE}Building current branch ($CURRENT_BRANCH)...${NC}" | ||||||||||||||
| git checkout "$CURRENT_BRANCH" --quiet | ||||||||||||||
| pnpm install --frozen-lockfile 2>&1 | grep -v "^$" | head -5 || true | ||||||||||||||
| pnpm run build 2>&1 | grep -v "^$" | tail -3 || true | ||||||||||||||
|
|
||||||||||||||
| echo -e "${BLUE}Measuring current branch sizes...${NC}" | ||||||||||||||
| pnpm exec size-limit --json > /tmp/current-sizes.json | ||||||||||||||
|
|
||||||||||||||
| # Compare sizes using the bundle-size script | ||||||||||||||
| node scripts/bundle-size.mjs compare --base /tmp/base-sizes.json --current /tmp/current-sizes.json | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # Skip bundle size check for current branch | ||
| # | ||
| # Usage: | ||
| # bin/skip-bundle-size-check | ||
| # | ||
|
|
||
| set -e | ||
|
|
||
| SKIP_FILE=".bundle-size-skip-branch" | ||
| BRANCH=$(git branch --show-current) | ||
|
|
||
| if [ -z "$BRANCH" ]; then | ||
| echo "Error: Not on a branch (detached HEAD?)" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Write comment header and branch name | ||
| cat > "$SKIP_FILE" << EOF | ||
| # This file allows skipping the bundle size CI check for a specific branch. | ||
| # When a branch name in this file matches the PR branch, the size check is skipped. | ||
| # | ||
| # Usage: Run \`bin/skip-bundle-size-check\` to set the current branch, then commit and push. | ||
| # | ||
| # This is useful when you have an intentional size increase that exceeds the 0.5KB threshold. | ||
| $BRANCH | ||
| EOF | ||
| echo "Set '$BRANCH' as the branch to skip bundle size check" | ||
| echo "" | ||
| echo "Next steps:" | ||
| echo " git add $SKIP_FILE" | ||
| echo " git commit -m 'Skip bundle size check for $BRANCH'" | ||
| echo " git push" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: shakacode/react_on_rails
Length of output: 110
🏁 Script executed:
Repository: shakacode/react_on_rails
Length of output: 267
🌐 Web query:
size-limit behavior missing target files npm package💡 Result:
Likely cause
Quick fixes to try
If that doesn't help
Sources
Citations:
🏁 Script executed:
Repository: shakacode/react_on_rails
Length of output: 3685
🏁 Script executed:
Repository: shakacode/react_on_rails
Length of output: 50
🏁 Script executed:
# Check the .size-limit.json file to understand its structure cat .size-limit.jsonRepository: shakacode/react_on_rails
Length of output: 3062
🏁 Script executed:
# Check the bundle-size.mjs script to see how it handles size-limit execution cat scripts/bundle-size.mjsRepository: shakacode/react_on_rails
Length of output: 9246
🏁 Script executed:
# View the full workflow file to understand the complete logic and error handling cat .github/workflows/bundle-size.ymlRepository: shakacode/react_on_rails
Length of output: 3402
🏁 Script executed:
Repository: shakacode/react_on_rails
Length of output: 734
🏁 Script executed:
Repository: shakacode/react_on_rails
Length of output: 150
Size-limit may fail when PR adds new bundle entries not present on base
You copy the PR's
.size-limit.jsonto the base branch and measure sizes without checking whether all configured paths exist. If a PR introduces new bundle entries pointing to files that don't exist on the base branch,size-limitwill error before producingbase-sizes.json, breaking the job.While the workflow includes a "Verify build artifacts" step (line 78), it only checks the three existing packages and doesn't validate all entries in the
.size-limit.jsonconfig. Consider either:.size-limit.jsonfor measurement if the PR's config is incompatible.🤖 Prompt for AI Agents