Files
twenty/packages/twenty-ui/scripts/checkPackSize.ts
T
Raphaël Bosi dd9ad876a4 Reduce published twenty-ui npm package size (#22087)
The published `twenty-ui@1.0.0-alpha.0` tarball was ~181 MB unpacked (27
MB compressed, 2,701 files). This was a build-config issue, so a clean
CI build would reproduce the same size.

Main fix: externalize `@tabler/icons-react` instead of bundling it. It
was forced into the bundle and aliased to the full icon barrel, inlining
the entire icon set into every entry point in both ESM and CJS (~81% of
the package). It stays a `dependency`, so consumers still get it; the
dynamic `<Icon name>` registry still resolves icons at runtime.

Also:
- Stop emitting/shipping declaration maps (`declarationMap: false`).
- Exclude the internal `dist/individual` build and `*.map` from the
tarball via `files` (it still builds locally for
`twenty-front-component-renderer`).
- Clean up the stale `files` / `project.json` build outputs at their
source, `scripts/generateBarrels.ts`.
- Add a `pack-size` CI guard (30 MB unpacked budget) and wire `size` +
`pack-size` into `ci-ui.yaml`.

Result: ~181 MB to ~2.3 MB unpacked (0.40 MB tarball, 400 files). All
export subpaths, types, and icon rendering verified intact in both
module formats.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22087?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-24 14:53:14 +00:00

48 lines
1.2 KiB
TypeScript

import { execSync } from 'child_process';
import * as path from 'path';
import { fileURLToPath } from 'url';
const MAX_UNPACKED_BYTES = 30 * 1024 * 1024;
const PACKAGE_PATH = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
'..',
);
const formatMegabytes = (bytes: number) =>
`${(bytes / (1024 * 1024)).toFixed(2)} MB`;
type NpmPackResult = {
filename: string;
size: number;
unpackedSize: number;
entryCount: number;
};
const output = execSync('npm pack --dry-run --json', {
cwd: PACKAGE_PATH,
encoding: 'utf-8',
maxBuffer: 64 * 1024 * 1024,
});
const [packResult] = JSON.parse(output) as NpmPackResult[];
if (packResult === undefined) {
throw new Error('npm pack did not return any package information');
}
const { size, unpackedSize, entryCount } = packResult;
if (unpackedSize > MAX_UNPACKED_BYTES) {
process.stderr.write(
`twenty-ui unpacked size ${formatMegabytes(unpackedSize)} exceeds budget ${formatMegabytes(
MAX_UNPACKED_BYTES,
)} (tarball ${formatMegabytes(size)}, ${entryCount} files)\n`,
);
process.exit(1);
}
process.stdout.write(
`twenty-ui pack OK: tarball ${formatMegabytes(size)}, unpacked ${formatMegabytes(
unpackedSize,
)}, ${entryCount} files\n`,
);