npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@node-cli/bundlesize

v4.6.2

Published

Simple CLI tool that checks file(s) size and report if limits have been reached

Readme

Node CLI Bundle Size package

npm

Bundlesize is a simple CLI tool that checks file(s) size and report if limits have been reached.

Installation

> npm install --dev @node-cli/bundlesize

Configuration

A configuration file must be provided via the -c parameter.

Type-Safe Configuration

For IDE autocompletion and validation, you can use either JSDoc type hints or the defineConfig helper function.

Using JSDoc (recommended for JavaScript configs)

// @ts-check
/** @type {import('@node-cli/bundlesize').BundlesizeConfig} */
export default {
  sizes: [
    {
      path: "dist/bundle.js",
      limit: "10 kB"
    }
  ]
};

Using defineConfig helper

// @ts-check
import { defineConfig } from "@node-cli/bundlesize";

export default defineConfig({
  sizes: [
    {
      path: "dist/bundle.js",
      limit: "10 kB"
    }
  ]
});

Both approaches provide:

  • Autocompletion for configuration options
  • Inline documentation for each property
  • Type validation in your IDE

Note: The // @ts-check comment enables TypeScript checking for the file, which is required for validation errors to appear.

Configuration Options

For the size option, it must export an object named "size" which is an array of objects with the following properties:

  • path: the path to the file to check
  • limit: the limit to check against

For the report option, it must export an object named "report" which is an object with the following properties:

  • header: the header to display (optional, string)
  • footer: the footer to display (optional, function receiving a boolean indicating if the limit has been reached, and a value corresponding to the diff. It must return a string)
  • previous: the previous path to the report to compare against (required, string)
  • current: the current path to the report to compare against (required, string)
  • columns: the columns to display (optional, array of objects)
  • threshold: the minimum gzip size change in bytes to consider as a change (optional, number, defaults to 0). Changes below this threshold are treated as no change.

Examples

Getting stats from files

Single file

export default {
  sizes: [
    {
      path: "dist/some-bundle.js",
      limit: "10 kB"
    }
  ]
};

Multiple files

export default {
  sizes: [
    {
      path: "dist/some-bundle.js",
      limit: "10 kB"
    },
    {
      path: "dist/some-other-bundle.js",
      limit: "100 kB"
    }
  ]
};

With glob patterns

export default {
  sizes: [
    {
      path: "dist/**/some-bundle.js",
      limit: "10 kB"
    },
    {
      path: "dist/**/some-other-bundle-*.js",
      limit: "100 kB"
    },
    {
      path: "dist/**/extra-+([a-zA-Z0-9]).js",
      limit: "100 kB"
    }
  ]
};

With aliases

export default {
  sizes: [
    {
      path: "dist/**/some-bundle.js",
      limit: "10 kB",
      alias: "Some bundle"
    },
    {
      path: "dist/**/some-other-bundle-*.js",
      limit: "100 kB",
      alias: "Some other bundle"
    },
    {
      path: "dist/**/extra-+([a-zA-Z0-9]).js",
      limit: "100 kB",
      alias: "Extra bundle"
    }
  ]
};

With a hash

The special keyword <hash> can be used to match a hash in the filename. It cannot used if multiple files match the pattern.

NOTE: Using <hash> is equivalent to using +([a-zA-Z0-9]) in the glob pattern. However, the result will be indexed with the hash key instead of the match key, so that subsequent scripts can use the hash value.

| Status | Pattern | Comment | | ------ | ------------------------------- | ------------------------------------ | | OK | dist/**/some-bundle-<hash>.js | If only one file matches the pattern | | Not OK | dist/**/same-prefix-<hash>.js | If multiple files match the pattern |

With a version

The special keyword <semver> can be used to match a version in the filename. It cannot be used if multiple files match the pattern.

NOTE: Using <semver> is equivalent to using * in the glob pattern. However, the result will be indexed with the semver key instead of the match key, so that subsequent scripts can use the semver value.

| Status | Pattern | Comment | | ------ | --------------------------------- | ------------------------------------ | | OK | dist/**/some-bundle-<semver>.js | If only one file matches the pattern | | Not OK | dist/**/same-prefix-<semver>.js | If multiple files match the pattern |

Printing reports from stats

Simple report

export default {
  report: {
    prev: "stats/previous.json",
    current: "stats/current.json"
  }
};

Simple report with custom header

export default {
  report: {
    header: "## My custom header",
    prev: "stats/previous.json",
    current: "stats/current.json"
  }
};

Simple report with custom footer

export default {
  report: {
    footer: (limitReached, diff) => {
      return `## My custom footer: ${limitReached} ${diff}`;
    },
    prev: "stats/previous.json",
    current: "stats/current.json"
  }
};

Simple report with custom columns

The columns option allows you to customize the report table columns. Each column is defined as an object with a key (column identifier) and value (column header text displayed in the table).

Available column keys:

| Key | Description | Default Header | | -------- | ---------------------------------------------------- | -------------- | | status | Shows ✅ if within limit, 🚫 if limit exceeded | "Status" | | file | Displays the file name or alias | "File" | | size | Shows the gzipped size with diff from previous stats | "Size (Gzip)" | | limits | Displays the configured size limit | "Limits" |

Default columns:

columns: [
  { status: "Status" },
  { file: "File" },
  { size: "Size (Gzip)" },
  { limits: "Limits" }
];

Customizing column headers:

You can change the header text while keeping the same column:

export default {
  report: {
    columns: [
      { status: "✓/✗" },
      { file: "Bundle" },
      { size: "Gzip Size" },
      { limits: "Max" }
    ],
    previous: "stats/previous.json",
    current: "stats/current.json"
  }
};

Removing columns:

You can remove columns by omitting them from the array:

export default {
  report: {
    columns: [{ file: "File" }, { size: "Size (Gzip)" }],
    previous: "stats/previous.json",
    current: "stats/current.json"
  }
};

Reordering columns:

You can change the column order by rearranging the array:

export default {
  report: {
    columns: [
      { file: "File" },
      { status: "Status" },
      { limits: "Limits" },
      { size: "Size (Gzip)" }
    ],
    previous: "stats/previous.json",
    current: "stats/current.json"
  }
};

Simple report with custom threshold

By default, all gzip size changes are reported. You can set a threshold to ignore small changes:

export default {
  report: {
    threshold: 10, // ignore changes smaller than 10 bytes
    prev: "stats/previous.json",
    current: "stats/current.json"
  }
};

Note on threshold with subgroups: When using subgroup headers, the threshold is applied consistently. If individual file changes are below the threshold (and thus treated as zero), the sub-bundle total will also reflect this. For example, if file A changes by +3 bytes and file B changes by +4 bytes with a threshold of 5, both individual changes are ignored, and the sub-bundle will show no change (even though the raw total would be +7 bytes).

Report with subgroup headers (multiple tables)

You can interleave header objects inside the sizes array to break the report output into multiple markdown tables. Each header object must contain a header property (any markdown heading is allowed). A sub-bundle total line will be printed after each group along with its diff to previous stats (if available), followed by the overall bundle size and status at the end.

export default {
  report: {
    header: "## Bundle Size With Groups",
    previous: "stats/previous.json",
    current: "stats/current.json"
  },
  sizes: [
    { header: "### Core" },
    { path: "dist/core.js", limit: "20 kB" },
    { path: "dist/core-extra.js", limit: "10 kB" },
    { header: "### Widgets" },
    { path: "dist/widget-a.js", limit: "15 kB" },
    { path: "dist/widget-b.js", limit: "15 kB" }
  ]
};

Example output:

## Bundle Size With Groups

### Core

| Status | File | Size (Gzip) | Limits |
| --- | --- | --- | --- |
| ✅ | core.js | 12.34 KB (-1.2 KB -8.80%) | 20 kB |
| ✅ | core-extra.js | 3.21 KB | 10 kB |

Sub-bundle size: 15.55 KB (-1.2 KB -7.17%)


### Widgets

| Status | File | Size (Gzip) | Limits |
| --- | --- | --- | --- |
| ✅ | widget-a.js | 5.00 KB (+500 B +10.84%) | 15 kB |
| ✅ | widget-b.js | 4.50 KB | 15 kB |

Sub-bundle size: 9.50 KB (+500 B +5.56%)


Overall bundle size: 25.05 KB (-700 B -2.72%)
Overall status: ✅

Notes:

  • If no header objects are present, the legacy single-table format is used (backwards compatible).
  • Headers are rendered in the order they appear in sizes.
  • Only size entries that resolve in the current stats are printed; missing ones are skipped silently.
  • Sub-bundle diff lines only show percentage / size diff when previous stats for at least one file in the subgroup exist.

Usage

Print the stats at the command line

"scripts": {
	"stats": "bundlesize -c bundlesize.config.js"
}

Print the stats in a file

"scripts": {
	"stats": "bundlesize -c bundlesize.config.js -o stats.json"
}

Print the stats in a file but do not fail if the limit is reached

"scripts": {
  "stats": "bundlesize -c bundlesize.config.js -o stats.json -s"
}

Add a prefix to the stats

"scripts": {
  "stats": "bundlesize -c bundlesize.config.js -o stats.json -p 'My prefix'"
}

Use the current package version as a prefix

"scripts": {
  "stats": "bundlesize -c bundlesize.config.js -o stats.json -p \"$npm_package_version\""
}

Compare current stats with the previous ones

"scripts": {
	"stats": "bundlesize -c bundlesize.config.js --type report"
}

Get help

> bundlesize --help

License

MIT © Arno Versini