Skip to content

michalsanger/nextjs-turbopack-bundle-size

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Next.js Turbopack Bundle Size

A GitHub Action that tracks Next.js App Router bundle sizes across pull requests. It stores a baseline for each branch and posts a route-by-route size comparison comment on every PR.

Usage

- name: Analyze bundle sizes
  uses: michalsanger/nextjs-turbopack-bundle-size@v1
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    minimum-change-threshold: 256
    budget-percent-increase-red: 20
    app-name: My App

The action must run after the app has been built with TURBOPACK_STATS=1. See examples/usage.yml for a complete single-app workflow, or examples/monorepo.yml for a matrix workflow covering multiple apps in a monorepo.

Example PR Comment

The action posts a comment like this on every pull request:

📦 My App — App Router Sizes (Turbopack)

This analysis was generated by the Next.js Turbopack Bundle Size action. 🤖

Route Size (gzipped) First load Diff (vs baseline)
global 214.5 KB 🟡 +1.2 KB
/ 85.2 KB 299.7 KB 🟢 -1.5 KB
/about 42.3 KB 256.8 KB 🔴 +3.1 KB
/blog 38.7 KB 253.2 KB ➖ No change
/dashboard 51.4 KB 265.9 KB 🟡 +800 B
/settings 29.1 KB 243.6 KB 🆕 New
/old-page 🗑️ Removed

Inputs

Input Required Default Description
github-token Yes GitHub token for downloading baseline artifact and posting PR comments
stats-path No .next/diagnostics/route-bundle-stats.json Path to the Turbopack stats file. Auto-detects legacy path .next/server/webpack-stats.json if the default doesn't exist.
artifact-name No turbopack-main-stats Artifact name prefix for storing baseline stats. The branch name is appended automatically (e.g. turbopack-main-stats-main).
minimum-change-threshold No 0 Byte threshold below which a size change is considered unchanged. For example, 500 means changes of 500 B or less are shown as "➖ No change".
budget-percent-increase-red No 0 Percentage threshold for flagging size increases as critical. Increases above this percentage show 🔴, others show 🟡. Default 0 means all increases show 🔴. For example, 20 means only increases above 20% are flagged red.
app-name No Application name in the report header (e.g. My App → "📦 My App — App Router Sizes (Turbopack)"). When set, the sticky PR comment uses bundle-size-report-{name} so matrix jobs for multiple apps do not overwrite each other. If not set, a generic header and the default comment key bundle-size-report are used.
baseline-workflow No Workflow file name (e.g. main.yml) to look up the baseline artifact in. Set this when the baseline artifact is uploaded by a different workflow than the one running this action. When unset, the artifact is searched in the current workflow.

Required Permissions

permissions:
  contents: read
  pull-requests: write
  actions: read

How It Works

  • On push to any branch: parses the stats file, computes gzip sizes for each route, and uploads the result as a GitHub Actions artifact (per branch).
  • On pull request: downloads the baseline artifact from the PR's target branch, parses the current stats file, calculates gzip sizes, and posts (or updates) a sticky comment with a route-by-route comparison table.

Comparing against branches other than your default

A PR is compared against a baseline stored for its target branch, so that branch needs a baseline — which means your workflow must run on pushes to it. The examples trigger on pushes to main, which covers the common case of PRs into main. To also compare PRs that target another long-lived branch (e.g. develop), add it to the push triggers:

on:
  push:
    branches: [main, develop]
  pull_request:

If no baseline exists for the target branch, the action falls back to the default branch's baseline (and, for repos upgrading from an older version, the previous unsuffixed artifact name).

Notes: Branch names are slugified into the artifact name (any character outside A-Za-z0-9._-, such as /, becomes -), so two branches differing only by such characters (e.g. feat/a and feat-a) would share a baseline. Each branch's baseline is kept under GitHub's default artifact retention (90 days); deleted branches leave an orphaned artifact until it expires.

Chunk files and the app-paths manifest are resolved relative to the .next directory inferred from stats-path, so pointing it to a subdirectory (e.g. apps/my-app/.next/diagnostics/route-bundle-stats.json) works correctly without any additional configuration. See examples/monorepo.yml for a complete monorepo setup.

Working directory in monorepos

Note: If your workflow uses defaults.run.working-directory to set a subdirectory (e.g. my-app), be aware that this only applies to run: steps — it does not apply to uses: steps like this action. You must include the subdirectory in stats-path:

stats-path: my-app/.next/diagnostics/route-bundle-stats.json

The first PR before any baseline exists will show all routes as "🆕 New" — this is expected.

Acknowledgements

Inspired by nextjs-bundle-analysis by HashiCorp.

About

A GitHub Action that tracks Next.js App Router bundle sizes across pull requests.

Resources

License

Stars

9 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors