Skip to content

Latest commit

 

History

History

README.md

@shiftescape/astro-bundle-budget

version downloads MIT License

Build-time JS/CSS bundle size budgets for Astro. Inspect every asset and page payload at the end of astro build — and optionally fail CI when you exceed your thresholds. 📊

▶ astro-bundle-budget  Analysing bundle…

  Asset                                                Type       Size
  ────────────────────────────────────────────────────────────────────
  assets/index-BxK92mPq.js                              js    42.3 kB
  assets/vendor-CHmL3xRz.js                             js    18.7 kB
  assets/hoisted-DqW1Pz9a.js                            js     3.1 kB
  assets/index-EpW3Kz7b.css                            css     6.4 kB
  ────────────────────────────────────────────────────────────────────
  Total JS                                              js    64.1 kB
  Total CSS                                            css     6.4 kB

  Budget violations

  ✗ assets/vendor-CHmL3xRz.js: 18.7 kB exceeds budget of 15 kB (+25% over)

  1 budget violation exceeded.

📦 Install

npm install -D astro-bundle-budget
# or
pnpm add -D astro-bundle-budget

🛠️ Usage

// astro.config.mjs
import { defineConfig } from "astro/config";
import bundleBudget from "astro-bundle-budget";

export default defineConfig({
  integrations: [
    bundleBudget({
      // Per-file limits — first matching glob wins
      budgets: [
        { path: "assets/vendor-*.js", budget: "50 kB" },
        { path: "**/*.js", budget: "100 kB" },
        { path: "**/*.css", budget: "20 kB" },
      ],

      // Per-page limits — total payload a single page may reference
      pageBudgets: [
        { type: "js", budget: "150 kB" },
        { type: "css", budget: "30 kB" },
        { type: "total", budget: "200 kB", compression: "gzip" },
      ],
    }),
  ],
});

⚡ Zero-config (size display only)

Add the integration with no options to get a free asset table after every build:

integrations: [bundleBudget()];

⚙️ Options

Option Type Default Description
budgets BudgetRule[] [] Per-file glob rules
pageBudgets PageBudget[] [] Per-page total payload rules
failOnExceed boolean true Exit 1 when a budget is exceeded
report boolean false Write bundle-budget-report.json to outDir
reportPath string 'bundle-budget-report.json' Report filename
verbose boolean false Show all assets + per-page breakdown

📋 BudgetRule

interface BudgetRule {
  path: string; // minimatch glob against asset path
  budget: number | string; // bytes or '100 kB', '1.5 MB'
  compression?: "none" | "gzip" | "brotli"; // default: 'none'
}

📄 PageBudget

interface PageBudget {
  type: "js" | "css" | "total"; // what to measure per page
  budget: number | string;
  compression?: "none" | "gzip" | "brotli";
}

📐 Size strings

Accepted formats: '100 kB', '1.5 MB', '50 KB', '200kb', '1.2 MiB', or a plain number (bytes).

🗜️ Compression

Set compression: 'gzip' or compression: 'brotli' to measure the wire size your users actually receive. Useful for pageBudgets targeting real-world performance.

🔄 CI integration

Because failOnExceed: true by default, astro build exits with code 1 when any budget is exceeded — no extra setup needed for GitHub Actions, GitLab CI, or any other CI platform.

To turn violations into warnings (still shows the table, never fails):

bundleBudget({ failOnExceed: false });

📋 JSON report

Enable report: true to write a machine-readable report to dist/bundle-budget-report.json:

{
  "generatedAt": "2025-03-21T10:00:00.000Z",
  "totalAssets": 4,
  "totalJsBytes": 65536,
  "totalCssBytes": 6553,
  "assets": [...],
  "pages": [...],
  "violations": [...],
  "passed": false
}

Store this file as a CI artefact and diff it between builds to track bundle growth over time.

⚖️ vs. alternatives

astro-bundle-budget vite-plugin-bundlesize rollup-plugin-visualizer
Astro-native config ❌ (Vite config)
Per-page breakdown
Fails the build
Compression budgets
Static HTML report JSON bundlemeta.json stats.html
Zero extra deps

📄 License

MIT