Skip to content

Commit c60cfeb

Browse files
committed
add size-limit and size-limit-action to measure sizes of individual exports/examples
1 parent 4cfffd0 commit c60cfeb

File tree

4 files changed

+245
-55
lines changed

4 files changed

+245
-55
lines changed

.github/workflows/size.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: size
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
permissions:
7+
pull-requests: write
8+
jobs:
9+
size:
10+
runs-on: ubuntu-latest
11+
env:
12+
CI_JOB_NUMBER: 1
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: EskiMojo14/size-limit-action@v2
16+
with:
17+
directory: library
18+
github_token: ${{ secrets.GITHUB_TOKEN }}
19+
package_manager: pnpm
20+
size_margin: non-zero

library/.size-limit.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import dedent from 'dedent';
2+
import type { Check, SizeLimitConfig } from 'size-limit';
3+
import * as v from './src';
4+
5+
const paths = ['dist/index.js', 'dist/index.cjs'];
6+
7+
const checks = paths.map(
8+
(path): Check => ({
9+
name: `Full bundle (${path.includes('.cjs') ? 'CJS' : 'ESM'})`,
10+
path,
11+
import: '*',
12+
})
13+
);
14+
15+
const importNames = new Set(Object.keys(v));
16+
17+
/**
18+
* Build a config for an individual export's size.
19+
* @param {string} importName Name of the export.
20+
* @returns {Check} The config.
21+
*/
22+
function individualExportConfig(importName: string): Check {
23+
return {
24+
name: `\`v.${importName}\``,
25+
// only check ESM individual exports
26+
path: paths[0],
27+
import: `{ ${importName} }`,
28+
};
29+
}
30+
31+
for (const importName of importNames) {
32+
// if it's a reserved name or internal, skip it
33+
if (importNames.has(importName + '_') || importName.startsWith('_')) continue;
34+
checks.push(individualExportConfig(importName));
35+
}
36+
37+
// a v.<name>( call
38+
const vRegex = /v\.(\w+)\(/g;
39+
40+
/**
41+
* Build a config for a TypeScript example's size.
42+
* @param {TemplateStringsArray} strings Template strings.
43+
* @param {...unknown} values Template values.
44+
* @returns {Check} The config.
45+
*/
46+
function ts(strings: TemplateStringsArray, ...values: unknown[]): Check {
47+
const dedented = dedent(strings, ...values);
48+
const usedImports = Array.from(dedented.matchAll(vRegex)).map((m) => m[1]);
49+
const uniqueImports = Array.from(new Set(usedImports)).map((importName) =>
50+
importNames.has(importName + '_') ? importName + '_' : importName
51+
);
52+
return {
53+
name: `\`\`\`ts\n${dedented}\n\`\`\``,
54+
// ESM only
55+
path: paths[0],
56+
import: `{ ${uniqueImports.join(', ')} }`,
57+
};
58+
}
59+
60+
checks.push(
61+
ts`
62+
v.object({
63+
email: v.pipe(v.string(), v.email()),
64+
password: v.pipe(v.string(), v.minLength(8)),
65+
})
66+
`
67+
);
68+
69+
export default checks satisfies SizeLimitConfig;

library/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,23 @@
4949
"lint.fix": "eslint \"src/**/*.ts*\" --fix",
5050
"format": "prettier --write ./src",
5151
"format.check": "prettier --check ./src",
52-
"build": "tsdown"
52+
"build": "tsdown",
53+
"size": "size-limit"
5354
},
5455
"devDependencies": {
5556
"@eslint/js": "^9.21.0",
57+
"@size-limit/esbuild": "^11.2.0",
58+
"@size-limit/preset-small-lib": "^11.2.0",
5659
"@vitest/coverage-v8": "^3.0.7",
60+
"dedent": "^1.7.0",
5761
"eslint": "^9.21.0",
5862
"eslint-plugin-import": "^2.31.0",
5963
"eslint-plugin-jsdoc": "^50.6.3",
6064
"eslint-plugin-redos-detector": "^3.1.1",
6165
"eslint-plugin-regexp": "^2.7.0",
6266
"eslint-plugin-security": "^3.0.1",
6367
"jsdom": "^26.0.0",
68+
"size-limit": "^11.2.0",
6469
"tsm": "^2.3.0",
6570
"tsdown": "^0.12.4",
6671
"typescript": "^5.7.3",

0 commit comments

Comments
 (0)