☰
Size Limit 版本演进全解读:从 0.1 到 14.2 的性能预算工具架构、插件体系与 CLI 实战指南
2026/10/15 15:43:48 网站建设 项目流程
  • 开发工具
  • 前端
  • 测试

【免费下载链接】size-limit

Calculate the real cost to run your JS app or lib to keep good performance. Show error in pull request if the cost exceeds the limit.

项目地址:https://gitcode.com/gh_mirrors/si/size-limit
点击查看免费下载

Size Limit 是一个面向 JavaScript 的性能预算(performance budget)工具:它在 CI 上检查每一次提交,计算你的 JS 对最终用户造成的真实成本(体积、下载时间、执行时间),一旦超出设定限额就抛出错误。本文以仓库根目录的 CHANGELOG.md 为骨架,结合packages/下的完整源码与测试,系统梳理从 0.1 初始发布到 14.2.0 的演进脉络,并给出当前版本的配置、命令行参数与插件体系的实战用法。读完你将掌握:如何从版本历史理解这套"模块化插件架构"的设计意图,如何按场景选用 preset 与插件,以及size-limit命令与配置文件的每一个可用参数。

它解决什么问题:性能预算与真实成本

项目的核心定位在 README.md 中表述得很清楚:"Size Limit is a performance budget tool for JavaScript. It checks every commit on CI, calculates the real cost of your JS for end-users and throws an error if the cost exceeds the limit."(Size Limit 是面向 JavaScript 的性能预算工具。它在 CI 上检查每一次提交,计算你的 JS 对终端用户的真实成本,一旦成本超出限额就抛出错误。)

从 CHANGELOG 最早的记录可以看到,这个定位是逐步打磨出来的:

  • 0.1(Initial release):第一个版本发布,并在 0.1.1 修复了"不带 kilo/mega 前缀解析B单位"的问题,说明从第一天起单位解析就是核心能力。
  • 0.3:只运行在第一个 CI job 上,以节省 CI 资源(对应源码中的ci-job-number依赖);0.4 增加 CircleCI 支持,0.5 增加 Semaphore 支持。
  • 0.11:忽略peerDependencies的大小——因为 peer 依赖通常由宿主项目提供,不应计入库自身的体积成本。这条规则至今保留在 get-config.js:let peer = Object.keys(pkg.packageJson.peerDependencies || {}); for (let check of config.checks) { if (peer.length > 0) check.ignore = peer.concat(check.ignore || []) }。

也就是说,从早期版本开始,Size Limit 就坚持"计算的不是裸文件大小,而是把依赖、polyfill 全部算进去的真实成本"这一理念。

从单体 CLI 到模块化插件架构

CHANGELOG 中最具分水岭意义的是2.0:"Rewrite tool with modular architecture"(用模块化架构重写工具)。它附带的迁移说明是:

  1. Updatesize-limitto 2.x version.
  2. Runnpx size-limit.
  3. Console will output instructions for installing necessary preset.

这套"迁移引导"机制在源码中依然可见:当找不到任何插件时,run.js 会调用help.showMigrationGuide(pkg)并process.exit(1);create-help.js 会根据项目类型推荐@size-limit/preset-app、@size-limit/preset-big-lib或@size-limit/preset-small-lib,甚至能根据yarn.lock/pnpm-lock.yaml自动把安装命令切换为yarn add --dev/pnpm add --save-dev。

插件如何被加载

模块化的关键在于"CLI 核心 + 独立插件包"的边界。插件加载逻辑集中在 load-plugins.js:它扫描项目的dependencies、devDependencies、optionalDependencies,凡是名字以@size-limit/或size-limit-开头的包,都会被动态import并取出其 default 导出(一个插件数组)。

  • 4.0将size-limit从dependencies移入peerDependencies,明确了"核心是宿主、插件是依赖"的边界。
  • 5.0.2修复了从optionalDependencies加载插件的问题。
  • 8.0正式支持第三方插件(只要命名符合size-limit-前缀),同时给 JSON 输出增加了limit字段。当前 README.md 列举了size-limit-node-esbuild、size-limit-preset-node-lib、nx-size-limit等第三方生态。
  • 10.0把整个项目迁移到 ESM("type": "module"),同时保证 CLI 依然能被 CJS 项目使用——这是 Node 生态迁移期的典型兼容策略。
  • 14.2.0为插件补齐了 TypeScript 类型:在 index.d.ts 中定义了Plugin接口、PluginStep(0 到 100 的步进号)、PluginHook、PluginConfig、PluginCheck等完整类型,第三方插件作者可以据此写出带类型提示的插件。

插件执行管线:step0 到 step100

插件的执行模型在 calc.js 中:核心会依次调用每个插件的before、step0、step1……step100、finally(finally即使某一步抛错也会执行,用于清理临时产物)。每个stepN都接收(config, check),并按"未被disablePlugins禁用"的 check 逐个执行;waitN则是该步 spinner 的文案。例如:

  • @size-limit/webpack在step20生成/加载 webpack 配置,在step40真正执行打包并产出bundles,在step61扣除"空 webpack 项目"自身的体积常量(见 packages/webpack/index.js 中WEBPACK_EMPTY_PROJECT_*系列常量);
  • @size-limit/file在step60计算最终体积;
  • @size-limit/time在step80计算加载时间与运行时间;
  • @size-limit/esbuild-why在step81生成体积分析报告。

这种"按步号编排、多插件接力"的模型,正是 2.0 模块化重写打下的基础:只要实现对应stepN,任何打包器(webpack/esbuild/rolldown)都能接入同一套计算管线。

预设(Preset)体系

预设是"按场景打包好的插件组合",在packages/preset-*/index.js中一目了然:

  • packages/preset-app/index.js:file+time,适合自带打包器、直接面向用户的 JS 应用;
  • packages/preset-big-lib/index.js:webpack+file+time,适合 > 10 kB 的大型库(如 React),需要测执行时间;
  • packages/preset-small-lib/index.js:rolldown+file,只测体积不测执行时间,适合 < 10 kB 的小库。

14.0.0把preset-small-lib的默认打包器从 esbuild 换成了 rolldown(这正是 13.1.0 新增 rolldown 插件后的自然结果),同时统一了各项目的 Node.js 支持并清理了依赖。理解这个"插件 + 预设"两层结构,是读懂整个 CHANGELOG 的关键钥匙。

打包器演进:webpack → esbuild → rolldown

CHANGELOG 清晰记录了打包器的三代更迭,这也是 Size Limit 计算"含依赖的真实体积"的技术底座:

阶段版本关键变化
webpack 时代0.12支持自定义 webpack 配置(0.12.1 修复其依赖解析)
0.15升级到 webpack 4(0.15.1/0.16.1 允许 CI 上用 Node 4 运行)
6.0升级到 webpack 5,并用 Statoscope 取代 Webpack Bundle Analyzer
esbuild 时代7.0新增@size-limit/esbuild插件(更快、node_modules占用更小),preset-small-lib迁到 esbuild;CSS 支持拆分为独立插件@size-limit/webpack-css;--why拆分为@size-limit/webpack-why
8.2新增@size-limit/esbuild-why插件
rolldown 时代13.1新增rolldown与rolldown-why插件
14.0preset-small-lib默认使用 rolldown;14.0.1 修复 rolldown 插件带来的体积增大问题

三个打包器插件的结构高度对称(对比 packages/webpack/index.js、packages/esbuild/index.js、packages/rolldown/index.js):都在step20准备配置(支持check.config指定的自定义配置,也支持modifyWebpackConfig/modifyEsbuildConfig/modifyRolldownConfig做最后微调),在step40执行打包,在step61从最终体积中减去"空工程自身"的常量(Brotli/gzip/无压缩、是否import等组合各有不同数值)。这样得到的size才是"你的库 + 依赖 + polyfill"的真实增量成本。

--why分析报告随打包器演进同步迭代:

  • webpack-why:基于 Statoscope,生成report.html与stats.json(见 packages/webpack-why/index.js);
  • esbuild-why:基于 esbuild-visualizer,默认生成esbuild-why.html并自动用浏览器打开;多检查时按name命名esbuild-why-{n}.html(见 packages/esbuild-why/index.js 与 packages/esbuild-why/report.js);
  • rolldown-why:基于 rollup-plugin-visualizer,命名规则相同,报告名是rolldown-why.html(见 packages/rolldown-why/index.js)。

对应地,--why的参数校验(parse-args.js)会按当前加载的打包器插件要求对应的*-why插件:用了 esbuild 就必须有@size-limit/esbuild-why,用了 rolldown 就必须有@size-limit/rolldown-why,否则抛argWithoutAnalyzer错误。

压缩策略演进:gzip 时代到 Brotli 默认

压缩算法是体积数字的直接决定因素,CHANGELOG 记录了两条主线:

  1. gzip 引入:0.14 新增gzip配置选项;0.5.1 让 Webpack Bundle Analyzer 使用 gzip 后的体积;4.5.3 修复了gzipped说明文字。
  2. Brotli 成为默认:3.0 首次引入 Brotli 支持;11.0正式把默认压缩从 gzip 切换为 Brotli,旧行为通过"gzip": true保留。

当前 packages/file/index.js 的step60完整实现了三态逻辑:

  • gzip === true:用createGzip({ level: 9 })计算 gzip 后体积;
  • brotli === false:不压缩,直接取文件原始大小;
  • 其余情况:用createBrotliCompress({ params: { [constants.BROTLI_PARAM_QUALITY]: 11 } })计算 Brotli 后体积(质量等级 11 是 Brotli 的最高压缩档)。

CLI 输出文案也随默认值变化:在 create-reporter.js 中,打包过的 check 默认显示 "with all dependencies, minified and brotlied",只有显式gzip: true才显示 "gzipped",brotli: false则显示 "with all dependencies and minified"——这正是 7.0.6 "Addedbrotliednote to CLI output" 与 11.0 默认切换的落地形态。

另一个与数字有关的细节是4.10.2 "Use1000factor forKBand1024forKiB":bytes.js 的formatBytes用 1000 进制显示kB/MB/GB…,而parseBytes的正则/^([+-]?\d+(?:\.\d+)?) *(?:([kmgtpezy])?(i)?b)?$/i同时支持十进制(10 kB= 10000 B)与 IEC 二进制(10 KiB= 10240 B)。

配置体系演进:从 sizeLimit 段到多格式配置文件

配置能力是 CHANGELOG 中出现频率最高的主题之一,其演进轨迹如下:

版本配置能力
0.6新增sizeLimit配置 section(旧名)
0.7sizeLimitsection 支持 glob 模式
0.8新增size-limit配置 section(现行名)
0.9弃用旧sizeLimitsection 名;弃用 CLI 中的 limit 参数
0.13新增.size-limit配置文件
0.17移除废弃的 limit CLI API,新增--limit参数
0.18新增.size-limit.js配置文件
0.20默认路径改用package.json#main
1.0新增.size-limit.json配置文件名
4.12.0新增.size-limit.cjs配置文件
11.1.0新增 TypeScript 配置支持
11.2.0新增--config参数;支持配置顶层await;新增time、message配置项

当前 get-config.js 用lilconfig统一查找,searchPlaces完整覆盖:package.json(size-limit段)、.size-limit.json、.size-limit、.size-limit.js、.size-limit.mjs、.size-limit.cjs、.size-limit.ts、.size-limit.mts、.size-limit.cts;loaders 覆盖.cjs/.cts/.js/.mjs/.mts/.ts六种扩展名,均通过动态import加载(这也是顶层await与export default/module.exports双语法得以支持的底层原因)。11.0.3 修复.mjs配置、10.0.2 修复 webpack 配置为函数时的支持(packages/webpack/index.js 的loadConfig会调用函数形式配置)都是这条链路上的打补丁记录。

配置项完整清单

以 index.d.ts 和 README.md 为准,每个 check 段可用的配置项如下:

  • path(必填):文件相对路径、glob 模式或数组,可用!排除,如["index.js", "dist/app-*.js", "!dist/app-exclude.js"];glob 展开逻辑见 get-config.js。
  • import:测试 tree-shaking 的按需导入。4.1 首次加入(Brian Schlenker 贡献),4.3 支持多文件,8.1 支持"*"表示导入全部导出。可以是"{ lib }"、"*",或{ "a.js": "{ a }", "b.js": "{ b }" }形式;process-import.js 会生成一个临时入口文件import …并console.log(...),交给打包器做 tree-shaking。
  • limit:体积或时间限额,格式如100 B、10 kB、500 ms、1 s。解析逻辑在 get-config.js:以ms/s结尾解析为timeLimit(并校验@size-limit/time插件存在),否则用parseBytes解析为sizeLimit。
  • name:多 check 段时的显示名称。
  • message:11.2 新增,超限时输出额外提示信息(见 create-reporter.js)。
  • entry:使用自定义打包配置时指定入口,字符串或数组;默认统计所有入口的总和。
  • webpack / rolldown / running:设为false可分别禁用对应插件阶段。
  • gzip / brotli:gzip: true用 gzip 并禁用 Brotli;brotli: false禁用一切压缩。
  • config:自定义 webpack/esbuild/rolldown 配置路径。
  • ignore:要排除的文件与依赖。
  • modifyWebpackConfig / modifyEsbuildConfig / modifyRolldownConfig:仅限.size-limit.js类配置使用,对打包配置做最后修改。
  • compareWith:--why模式下与另一份stats.json对比。
  • uiReports:自定义 UI 报告列表(webpack/Statoscope)。
  • disablePlugins:12.1 新增,按 npm 包名跳过指定插件(如"@size-limit/time")。实现见 calc.js 的isPluginDisabled,校验见 get-config.js。
  • time:11.2 新增,{ networkSpeed, latency, loadingMessage }三个子项用于自定义加载时间模型,归一化逻辑见 get-config.js。

另外两条自动规则值得注意:peerDependencies会自动并入ignore(0.11 起);当 check 没有path也没有entry时,默认取package.json#main(0.20 起),若无main则取exports的根入口,再退化为index.js——14.2.0 "Useexportsfor the default path on nomain" 补全的正是这条链(见 get-config.js 与 exportsEntry)。

免配置用法

不写配置文件也可以直接用 CLI 传参(README "Also, you avoid having a config and pass the limit to CLI"):

npm install --save-dev @size-limit/file npx size-limit --limit "10 kB" dist/bundle.js

以及指定配置文件位置:

npx size-limit --config configs/size-limit.json

--config还支持把配置文件放在任意子目录(测试 get-config.test.js 验证了src/configs/my-size-limit.config.js场景,配置内路径会以该文件所在目录为基准解析)。

CLI 参数演进与完整手册

CLI 参数几乎都是一步步累积出来的,parse-args.js 是现行实现的完整清单,create-help.js 是自带的帮助文本。按引入版本整理:

参数引入版本说明
--limit LIMIT0.17(取代旧 limit API)覆盖配置中的限额
--json1.2JSON 输出(4.5.7 起 JSON 模式不再显示 spinner)
--save-bundle DIR1.3(4.8 起支持 webpack stats)把构建产物写到磁盘供人工检查
--why1.3 前已有,7.0 拆到*-why插件展示体积构成分析报告
--debug2.1输出内部配置 JSON,用于提交 issue(debug.js)
--watch4.4监听文件变化自动重跑(底层用fs.watch,12.0 起取代 chokidar)
--clean-dir4.5配合--save-bundle,构建前清空目标目录
--hide-passed4.6只输出未通过的 check
--highlight-less4.7(4.9 起体积型 limit 自动开启)突出显示"比限额小"的包
--silent4.10只显示失败的限额(1.3.7 修复--no-gzip,8.1.2 修复静默模式)
--compare-with FILE6.0 前后(需--why)与另一份 stats.json 对比
--config FILE11.2指定配置文件
--ignore-missing14.1跳过没有匹配文件的 check(workspace 只构建部分项目时用)

几个容易踩坑的校验逻辑(全部在 parse-args.js 中):

  • --save-bundle要求已加载webpack/esbuild/rolldown任一插件,且必须带目录参数;
  • --clean-dir只能在出现--save-bundle时使用;
  • --compare-with要求同时满足"有 webpack + webpack-why 插件"且"已使用--why";
  • 未知参数直接抛unknownArg错误。

14.1.0还为--save-bundle增加了"多 check 写入同一目录可能互相覆盖"的警告(见 create-reporter.js)。运行结束后的退出码行为在 run.js:config.failed || config.missed时process.exit(1),这正是 CI 集成"超限即失败"的实现基础。

度量能力演进:从字节到真实耗时

体积(字节)只是第一代度量,CHANGELOG 记录了向"时间"度量的进化:

  • 1.1:开始计算"下载 + 执行 JS 的时间",并改进 CLI UI;1.1.2 修复webpack: false时的运行时间计算;2.1.1 忽略非.js/.mjs文件以加速计算并修正口径;2.1.5 修复并行任务下的运行时间计算。
  • 2.2.3 / 2.2.4 / 4.5.3:反复修复MaxListenersExceededWarning(计算任务过多导致 Node 事件监听器超限),14.2.0 进一步优化为"小规模检查不再降低进程监听器上限"——对应 calc.js 中listeners > process.getMaxListeners()才setMaxListeners的条件逻辑。
  • 9.0:time 插件改用 CDN 上的 React 作为基准样本(见 get-running-time.js 中的EXAMPLE常量)。
  • 11.2.0:配置中新增time选项,可自定义网络速度与延迟。

time 插件的完整实现位于 packages/time/index.js 与 packages/time/get-running-time.js:

  • 加载时间模型:默认按 slow 3G 的50 * 1024B/s(SLOW_3G常量)计算,size / networkSpeed得到下载时间,再加上latency得到loadTime;
  • 运行时间模型:用 estimo 在 headless Chrome(或本机已装的桌面 Chrome,1.3.8 起不再重复下载)中真实执行 JS 三次取平均,再乘以"本机性能相对低端 Android 设备(Snapdragon 410)的 throttling 倍率",得到runTime;throttling 倍率有本地缓存(cache.js)并支持SIZE_LIMIT_FAKE_TIME环境变量注入假时间以便测试;
  • 最终totalTime = runTime + loadTime;"running": false时只算加载时间。

输出样例(README 中的真实输出格式,由 create-reporter.js 渲染):

Package size: 30.08 kB with all dependencies, minified and brotlied Loading time: 602 ms on slow 3G Running time: 214 ms on Snapdragon 410 Total time: 815 ms

质量与兼容性演进:Node、Windows、包管理器与依赖精简

CHANGELOG 后半段大量篇幅属于工程治理,理解这些有助于判断你在什么环境能安全升级:

  • Node.js 版本策略:0.15 移除 Node 4 → 0.22 移除 Node 6 → 3.0 移除 Node 8 → 5.0 移除 Node 10 → 8.0 移除 Node 12 → 9.0 移除 Node 14/16 → 12.0 移除 Node 18 → 13.0 移除 Node 20。当前 14.2.0 的engines为^22.19.0 || ^24.5.0 || >=26.0.0(见 packages/size-limit/package.json)。中途还有 4.5.5 因 ES modules bug 放弃 Node.js 13.0-13.6、1.1.1/0.16.1/0.15.1 允许 CI 上用旧版 Node 等细节。
  • Windows 支持:4.4.3、4.4.5、11.1.1 三度修复。
  • 包管理器兼容:3.0.1 支持 Yarn PnP 与 Yarn 2;4.4.4 修复 Yarn 2;5.0.3 修复 pnpm;7.0.5 给迁移指南补了 pnpm 示例。
  • 依赖精简:4.9.1 用lilconfig取代cosmiconfig;5.0.4/5.0.5 依次用nanocolors、picocolors替换colorette;6.0.1 用nanospinner替换mico-spinner;13.0.3 移除picocolors;13.0.0 移除tinyglobby与jiti(glob 改由 Node 内置fs.glob实现,见 get-config.js);12.0.0 用内置fs.watch取代chokidar,并把jiti降为可选依赖。当前核心包依赖仅剩lilconfig与nanospinner两个。
  • 发布与供应链:8.2.x、13.0.1、13.1.1 多次修复 npm 发布流程;13.0.0 启用 npm provenance(供应链溯源)。

JS API 与 CI 集成

2.2加入 JS API,2.2.2修复了它。当前入口 packages/size-limit/index.js 接收"插件数组 + 文件路径/配置对象",返回每个 check 的{ size, time, runTime, loadTime };它同时导出processImport与SizeLimitError(size-limit-error.js 定义了全套带占位符的中文/英文错误消息,并对空配置、非数组配置等错误附带修复示例 JSON)。README 中的用法示例:

const sizeLimit = require('size-limit') const filePlugin = require('@size-limit/file') const webpackPlugin = require('@size-limit/webpack') sizeLimit([filePlugin, webpackPlugin], [filePath]).then(result => { result //=> { size: 12480 } })

CI 集成方面,README 提供了基于andresz1/size-limit-action的 GitHub Actions 示例(.github/workflows/size-limit.yml),配合CI_JOB_NUMBER: 1环境变量即可实现"PR 评论中展示体积变化并在超限时拒绝"的闭环;CHANGELOG 中 0.3"只在第一个 CI job 运行"、0.4/0.5 的 CircleCI/Semaphore 支持、1.3.2 的 CircleCI 警告、1.3.5/1.3.4 的 CI 警告文案与样式修复,都是这一能力的历史铺垫。

版本演进时间线速查

版本里程碑
0.1初始发布
0.6–0.8sizeLimit/size-limit配置段、glob 支持
0.9UglifyJS 3、弃用旧配置段名与 CLI limit
1.0–1.2.size-limit.json、--json
1.3--save-bundle
2.0模块化架构重写(插件 + 迁移引导)
2.1–2.2--debug、JS API
3.0Brotli 支持、移除 Node 8
4.0–4.12peerDependencies、tree-shakingimport、--watch、--clean-dir、--hide-passed、--highlight-less、--silent、KB/KiB 因子、.size-limit.cjs
5.0–6.0移除 Node 10、webpack 5、Statoscope
7.0esbuild 插件、webpack-css、webpack-why 拆分
8.0–8.2第三方插件、esbuild-why
9.0–10.0移除 Node 14/16、全项目 ESM 化
11.0–11.2Brotli 默认、TypeScript 配置、--config、time/message选项
12.0–12.1fs.watch取代 chokidar、disablePlugins
13.0–13.1移除 Node 20、rolldown/rolldown-why、npm provenance
14.0–14.2preset-small-lib 默认 rolldown、--ignore-missing、exports 默认入口、插件类型

结语

从 0.1 的"一个能算 gzip 体积的命令行工具"到 14.2 的"模块化插件 + 三种打包器 + 时间度量 + 完整 CI 集成"的生态,Size Limit 的 CHANGELOG 本身就是一篇关于性能预算工具如何做架构演进的案例。对使用者而言,最实用的结论是:

  • 小库用@size-limit/preset-small-lib(rolldown + file,只测体积),大库用@size-limit/preset-big-lib(webpack + file + time),应用用@size-limit/preset-app(file + time);
  • 配置优先写进package.json的size-limit段,复杂场景用.size-limit.js/.size-limit.ts(支持modify*Config与顶层await);
  • CI 上把size-limit挂进测试脚本(npm test追加&& npm run size),配合--json、--hide-passed、--ignore-missing等参数控制输出与失败策略;
  • 需要定位体积构成时,用--why+ 对应的*-why插件生成可视化报告。

如需深入源码,建议从 packages/size-limit/run.js、packages/size-limit/calc.js、packages/size-limit/get-config.js 三个文件入手,配合 packages/size-limit/test/ 下的测试用例(如 get-config.test.js、run.test.js)验证各参数与配置项的实际行为。

  • 开发工具
  • 前端
  • 测试

【免费下载链接】size-limit

Calculate the real cost to run your JS app or lib to keep good performance. Show error in pull request if the cost exceeds the limit.

项目地址:https://gitcode.com/gh_mirrors/si/size-limit
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询