Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ name: CI

on:
push:
branches:
branches:
- main
- release-v*
pull_request:
branches:
branches:
- main
- release-v*

Expand Down Expand Up @@ -107,6 +107,40 @@ jobs:
- name: Run TypeScript type check
run: pnpm run type-check:full

bundle-size:
name: 'Bundle Size Check'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10.11.0

- name: Use Node.js 22
uses: actions/setup-node@v5
with:
node-version: 22
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build packages
run: pnpm run build:packages

- name: Check bundle size
run: cd packages/ai && pnpm run check-bundle-size

- name: Upload bundle size metafiles
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: bundle-size-metafiles
path: packages/ai/dist-bundle-check/*.json

test_matrix:
name: 'Test'
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
.turbo
dist
dist-ssr
dist-bundle-check
examples/*/build
node_modules
public/dist
Expand Down
5 changes: 4 additions & 1 deletion packages/ai/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"test:update": "pnpm test:node -u",
"test:watch": "vitest --config vitest.node.config.js",
"test:edge": "vitest --config vitest.edge.config.js --run",
"test:node": "vitest --config vitest.node.config.js --run"
"test:node": "vitest --config vitest.node.config.js --run",
"check-bundle-size": "tsx scripts/check-bundle-size.ts"
},
"exports": {
"./package.json": "./package.json",
Expand Down Expand Up @@ -64,9 +65,11 @@
"@types/json-schema": "7.0.15",
"@types/node": "20.17.24",
"@vercel/ai-tsconfig": "workspace:*",
"esbuild": "^0.24.2",
"eslint": "8.57.1",
"eslint-config-vercel-ai": "workspace:*",
"tsup": "^7.2.0",
"tsx": "^4.19.2",
"typescript": "5.8.3",
"zod": "3.25.76"
},
Expand Down
119 changes: 119 additions & 0 deletions packages/ai/scripts/check-bundle-size.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { build } from 'esbuild';
import { writeFileSync, statSync } from 'fs';
import { join } from 'path';

// Bundle size limits in bytes
const LIMIT = 510 * 1024;

interface BundleResult {
size: number;
path: string;
condition: string;
}

async function bundleForNode(): Promise<BundleResult> {
const outfile = join(process.cwd(), 'dist-bundle-check', 'node.js');
const metafile = join(process.cwd(), 'dist-bundle-check', 'node-meta.json');

const result = await build({
entryPoints: [join(process.cwd(), 'src', 'index.ts')],
bundle: true,
platform: 'node',
target: 'es2020',
format: 'esm',
outfile,
metafile: true,
minify: true,
treeShaking: true,
external: ['arktype', 'effect', '@valibot/to-json-schema'],
});
writeFileSync(metafile, JSON.stringify(result.metafile, null, 2));

const size = statSync(outfile).size;
return { size, path: outfile, condition: 'node' };
}

async function bundleForBrowser(): Promise<BundleResult> {
const outfile = join(process.cwd(), 'dist-bundle-check', 'browser.js');
const metafile = join(
process.cwd(),
'dist-bundle-check',
'browser-meta.json',
);

const result = await build({
entryPoints: [join(process.cwd(), 'src', 'index.ts')],
bundle: true,
platform: 'browser',
target: 'es2020',
format: 'esm',
outfile,
metafile: true,
minify: true,
treeShaking: true,
conditions: ['browser'],
external: ['arktype', 'effect', '@valibot/to-json-schema'],
});
writeFileSync(metafile, JSON.stringify(result.metafile, null, 2));

const size = statSync(outfile).size;
return { size, path: outfile, condition: 'browser' };
}

function formatSize(bytes: number): string {
return `${(bytes / 1024).toFixed(2)} KB`;
}

function checkSize(result: BundleResult, limit: number): boolean {
const passed = result.size <= limit;
const status = passed ? '✅' : '❌';
const percentage = ((result.size / limit) * 100).toFixed(1);

console.log(
`${status} ${result.condition.padEnd(10)} ${formatSize(result.size).padEnd(12)} (${percentage}% of ${formatSize(limit)} limit)`,
);

return passed;
}

async function main() {
console.log('📦 Checking bundle sizes...\n');

try {
const [nodeResult, browserResult] = await Promise.all([
bundleForNode(),
bundleForBrowser(),
]);

console.log('Bundle sizes:');
const nodePass = checkSize(nodeResult, LIMIT);
const browserPass = checkSize(browserResult, LIMIT);

console.log('\n---');

console.log('📦 Bundle size check complete.');
console.log(
'Upload dist-bundle-check/*.json files to https://esbuild.github.io/analyze/ for detailed analysis.',
);

console.log('\n---');

if (nodePass && browserPass) {
console.log('✅ All bundle size checks passed!');
process.exit(0);
} else {
console.log('❌ Bundle size check failed!');
console.log('\nTo fix this, either:');
console.log('1. Reduce the bundle size by optimizing code');
console.log(
'2. Update the limit at https://github.com/vercel/ai/settings/variables/actions/BUNDLE_SIZE_LIMIT_KB',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message suggests updating a GitHub Actions variable BUNDLE_SIZE_LIMIT_KB, but the script uses a hardcoded limit and doesn't read from any environment variable, making this guidance ineffective and misleading.

View Details
📝 Patch Details
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1b3e5e73c..8b415be31 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -132,6 +132,8 @@ jobs:
         run: pnpm run build:packages
 
       - name: Check bundle size
+        env:
+          BUNDLE_SIZE_LIMIT_KB: ${{ vars.BUNDLE_SIZE_LIMIT_KB }}
         run: cd packages/ai && pnpm run check-bundle-size
 
       - name: Upload bundle size metafiles
diff --git a/packages/ai/scripts/check-bundle-size.ts b/packages/ai/scripts/check-bundle-size.ts
index ff8cf4ad0..610c3713e 100644
--- a/packages/ai/scripts/check-bundle-size.ts
+++ b/packages/ai/scripts/check-bundle-size.ts
@@ -3,7 +3,9 @@ import { writeFileSync, statSync } from 'fs';
 import { join } from 'path';
 
 // Bundle size limits in bytes
-const LIMIT = 510 * 1024;
+const LIMIT = process.env.BUNDLE_SIZE_LIMIT_KB
+  ? parseInt(process.env.BUNDLE_SIZE_LIMIT_KB, 10) * 1024
+  : 510 * 1024;
 
 interface BundleResult {
   size: number;

Analysis

Bundle size check error message references non-functional GitHub Actions variable

What fails: The check-bundle-size.ts script error message at line 109 instructs users to update BUNDLE_SIZE_LIMIT_KB at https://github.com/vercel/ai/settings/variables/actions/BUNDLE_SIZE_LIMIT_KB, but the script hardcodes the limit at line 6 (const LIMIT = 510 * 1024;) and never reads from environment variables.

How to reproduce:

# The script uses hardcoded value:
cd packages/ai
grep "const LIMIT" scripts/check-bundle-size.ts
# Output: const LIMIT = 510 * 1024;

# The script doesn't use process.env:
grep "process.env" scripts/check-bundle-size.ts
# Output: (none)

# CI workflow doesn't pass the variable:
grep -A5 "Check bundle size" .github/workflows/ci.yml
# Shows no env vars passed to the script

Result: When a bundle size check fails, users follow the error message guidance to update the GitHub Actions variable, but the script continues failing because it never reads that variable. This wastes developer time troubleshooting why their configuration change has no effect.

Expected: The script should read from process.env.BUNDLE_SIZE_LIMIT_KB and the CI workflow should pass to the script, making the error message's guidance functional.

Fix: Modified the script to read from environment variable with fallback to hardcoded default, and updated the CI workflow to pass the GitHub Actions variable per GitHub Actions variables documentation.

);
process.exit(1);
}
} catch (error) {
console.error('Error during bundle size check:', error);
process.exit(1);
}
}

main();
Loading
Loading