# nextjs-bundle-analysis turns a pull request into a bundle size comment

> nextjs-bundle-analysis is a GitHub Action and CLI that compares a pull request's Next.js bundle against the base branch and posts the difference as a pull request comment, with optional performance budgets. It suits teams that want bundle regressions visible in review, and it is blind to third party script tags.

**hashicorp/nextjs-bundle-analysis** — A github action that provides detailed bundle analysis on PRs for next.js apps

- Repository: https://github.com/hashicorp/nextjs-bundle-analysis
- Stars: 677 · Forks: 38
- Language: JavaScript
- License: MPL-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/hashicorp-nextjs-bundle-analysis

## A comment on the pull request instead of a dashboard to remember

The problem this addresses is that bundle size regressions are easy to introduce and hard to notice. A dependency upgrade lands, a component starts pulling in a date library, and the page gets slower for every visitor while the review screen shows a clean diff of application code. nextjs-bundle-analysis puts the number where reviewers already are. It analyzes each pull request's impact on a Next.js app's bundle size and displays it in a comment attached to the pull request, so the change in first load size becomes part of the conversation about the change itself. That framing is the whole design. A separate bundle dashboard is a place people forget to look, and by the time a report exists the offending commit is already merged. Optional performance budgets are supported on top of the comment, which turns the report from a number into a threshold. The project comes from HashiCorp and is published under the Mozilla Public License 2.0, and the author field in the package manifest names Jeff Escalante.

## Three executables, one of which is the generator

The package is more than the action. The manifest declares three binaries, which tells you the tool has three distinct jobs:

```json
  "bin": {
    "generate": "./generate.mjs",
    "report": "./report.js",
    "compare": "./compare.js"
  },
```

generate is the setup helper that scaffolds the workflow file, report produces the analysis comment from a built application, and compare performs the diff between two sets of bundle output. The action template lives in template.yml at the repository root, and the implementation files sit next to it: generate.js and generate.mjs for the generator, report.js for the reporting, compare.js for the comparison, and utils.js for shared helpers. Tests live in a __tests__ directory and run under jest, with fixtures excluded through the testPathIgnorePatterns setting in the package manifest. The runtime dependencies are small and reveal what the tool actually does: filesize and gzip-size to format byte counts in both raw and compressed form, number-to-words to spell out route names in the comment, picocolors for terminal output, mkdirp to create directories, and @clack/prompts for the interactive prompts the generator asks.

## Setting it up with one npx command

Installation is a single command that asks a few questions. It creates a .github/workflows directory in the project root and writes a next_bundle_analysis.yml file into it:

```bash
$ npx -p nextjs-bundle-analysis generate
```

The interactive prompts come from @clack/prompts, and the generator asks for the details it needs to write a working workflow, such as the default branch and where the Next.js application lives. The generated file is not treated as sacred. The readme says you can edit the workflow file directly to adjust the default branch or the directory your app lives in, which matters if you use a srcDir layout or otherwise moved things out of the project root. The configuration itself, though, is not in the workflow file. Config values are written to package.json under the key nextBundleAnalysis, and can be changed there at any time, which keeps the tunables with the rest of your project metadata and makes them reviewable in a dependency bump or a config change pull request.

## Budgets, thresholds and the two knobs that decide what gets reported

The option set is small and each option changes what a reviewer sees. The budget option is a number in bytes for first page load size, so a budget of 358400 means 350 KB, and a page whose first load is 248 KB is listed as having used 70 percent of the budget. If a budget is set, budgetPercentIncreaseRed is required, and it controls when a page that grew past a given percentage is flagged with a red marker to draw attention to the change. minimumChangeThreshold works the other way, setting a floor under which pages are treated as unchanged, so a threshold of 500 means a page that grew by 300 bytes is not reported at all. showDetails, which defaults to true, renders a collapsed details section under each part of the comment explaining the finer points of the numbers, and can be turned off for teams who already know what the figures mean. alwaysShowGzipDiff forces the compressed size difference to appear in the table even when a budget is set, and skipCommentIfEmpty, defaulting to false, makes the generated comment an empty string when no page changed size, which is the option that keeps a quiet pull request quiet.

## The comparison model needs a base, so the first run fails on purpose

The mechanism is a diff against a baseline, and that has a consequence the readme calls out directly. Because the tool works by comparing the base bundle against each pull request, the first time it runs there is no base to compare against and it fails. This is expected behaviour rather than a bug. The suggested remedy is to commit directly to the default branch first, where the action runs to generate the base bundle, and then any branch that forks after that point has a valid comparison point. That is a deployment detail with a real operational footprint: the action has to be able to write a base artifact somewhere durable, and pull requests opened before the base exists will look like failures. The build step is the other assumption baked into the workflow. The action step is called Build next.js app and it assumes that running next build successfully builds your application. If your real build needs extra scripts or logic, you have to edit that step yourself, and the project says it plans to make this configurable through the generator in the future. It is not configurable today, so treat the generated workflow as a starting draft you are expected to edit.

## The blind spot is every script tag you did not build

There is one limitation that should decide whether the tool is worth having. The analysis covers only the direct bundle output from Next.js. Any script added through a script tag, especially third party scripts and things like analytics or other tracking scripts, is not included in the numbers. The readme argues that scripts of that kind should probably be loaded behind a consent manager and should not affect initial load, and that as long as that is how you handle them the difference does not matter. That argument holds only if you actually follow it. If your app loads an analytics bundle in the head, the reported first load size is smaller than what a user experiences, and the budget percentage is computed against a number that is not the number users wait for. The readme is candid that you need to account for the extra size added by those scripts separately, which means for some teams the honest conclusion is that the tool reports a partial picture. There is no configuration option to include external scripts, since the tool reads the build output rather than the network, so the gap cannot be closed with configuration.

## Release cadence, packaging and the state of the repository

The repository has a flat, readable structure: the four implementation files, a template, a tests directory, a package-lock.json and a .changeset directory. The .changeset directory is the release mechanism, and the manifest shows a changeset driven release with two scripts, changeset publish for a normal release and a canary variant published under the canary tag. The tag list bears out how that has been used, with v0.5.0 on 2023-04-07 and a canary tag built the same day alongside it, then a later canary tag v0.5.1-canary-20230413215203 on 2023-04-13. The package version still reads 0.5.0. So the published versions are old while the working tree has continued to receive commits, with the last push on 2026-05-11. For an adopter that means the action is referenced by a version tag that is over three years old, and the practical question is whether the workflow file you generate today matches the current state of the code that produces the comment. The package is published to npm, and the licence is MPL-2.0, which is a file level copyleft licence, so a modified copy of the files that carry the notice obligations, while unmodified use in a CI workflow is not something the licence asks you to publish.

## Conclusion

nextjs-bundle-analysis is worth adopting for a Next.js team that wants bundle size to appear in pull request review instead of in a separate dashboard nobody opens, provided you accept a comparison model that needs a base bundle committed to the default branch. It is the wrong tool for apps that load most of their weight through third party script tags, and for a build pipeline whose real command is not next build, since the workflow hardcodes that assumption. Verify first that the first run on your default branch succeeds and produces a base, then check the budget value against a page you already know is fast. The last push was on 2026-05-11 and the newest release tag is v0.5.0 from 2023-04-07.

## FAQ

### How do I install nextjs-bundle-analysis?

Run npx -p nextjs-bundle-analysis generate and answer the prompts. The command creates a .github/workflows directory in the project root and adds a next_bundle_analysis.yml file to it.

### Where do I configure nextjs-bundle-analysis options?

Config values are written to package.json under the key nextBundleAnalysis and can be changed there at any time. The workflow file itself is meant to be edited by hand for the default branch or the directory your Next.js app lives in.

### Why does the nextjs-bundle-analysis action fail on the first pull request?

The tool compares the base bundle against each pull request, so the first run has no base to compare against and fails by design. Commit to the default branch first so the action generates a base bundle that later branches can be compared against.

### Does nextjs-bundle-analysis count third party script tags?

No. It only analyzes the direct bundle output from Next.js, so analytics, tracking and other third party scripts loaded through a script tag are not included and have to be accounted for separately.

### What does the budget option do in nextjs-bundle-analysis?

It sets a first page load size budget in bytes, so a budget of 358400 means 350 KB. A page at 248 KB is then reported as using 70 percent of the budget, and budgetPercentIncreaseRed is required whenever a budget is set.

## Sources

- [hashicorp/nextjs-bundle-analysis on GitHub](https://github.com/hashicorp/nextjs-bundle-analysis)
- [Issues](https://github.com/hashicorp/nextjs-bundle-analysis/issues)
- [License: MPL-2.0](https://github.com/hashicorp/nextjs-bundle-analysis/blob/main/LICENSE)
- [README](https://github.com/hashicorp/nextjs-bundle-analysis/blob/main/README.md)
- [Releases](https://github.com/hashicorp/nextjs-bundle-analysis/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hashicorp-nextjs-bundle-analysis
