Commit Graph

2 Commits

Author SHA1 Message Date
Maxim 60d3ef1071 fix(react-native): externalize react-dom in the headless size measurement
The esbuild `external` list omitted `react-dom`, unlike react-core's
measure-copilotchat.mjs, so a stray web-oriented edge could be absorbed
into the figure the PR's bundle claim rests on.

Checked empirically before changing anything: `react-dom` is NOT reachable
from @copilotkit/react-native/headless today. A metafile run shows 0 of the
653 input modules are react-dom, and no module references it even
pre-resolution. The reported figure is therefore UNCHANGED — 94941 B gzip
(92.7 kB) before and after, byte for byte. The headline "92.8 kB -> 92.7 kB,
flat" claim is unaffected and stays comparable with previously reported
numbers.

The guard is still worth having. Simulating a stray edge measures the
inflation it prevents: +56.3 kB gzip via react-dom/client, +57.3 kB via
react-dom/server (not the ~130 kB estimated in review — that is closer to
the raw magnitude; react-dom-client.production.js is 536 kB raw). The
subtler case is a bare `react-dom` edge at +1.4 kB, small enough to read as
noise while still being a real regression.

No subpath entries: esbuild prefix-matches package paths, so `react-dom`
already covers react-dom/client and react-dom/server (verified on the
pinned 0.27.3; esbuild CHANGELOG 0.5.14 and 0.14.13). Listing them would
imply they were required.

Hoisted the list to an exported HEADLESS_EXTERNAL with per-entry rationale,
mirroring the sibling's DEFAULT_EXTERNAL, and made `external` an overridable
option so the new test can A/B it rather than assert on a literal. Both new
tests fail if react-dom is removed from the list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 23:16:32 +02:00
Maxim 63a1c94fbb fix(react-native): make the headless size measurement fail loudly, not print 0.0 kB
measure-headless.mjs prints the number the PR's bundle claim rests on, and it
had three ways to report a broken run as a good one. All three reproduced:

1. No zero-output guard (the react-core sibling has one). A run whose bundle
   collapses to nothing measures ~20-35 B of gzip envelope, prints "0.0 kB"
   and exits 0 — reported into the CI job summary as a spectacular win. Note a
   zero-ONLY guard would not have caught the reproduction (35 B, not 0), so
   this adds a plausibility FLOOR of 8 kB alongside the zero check: ~11x below
   the real 92.7 kB, so legitimate size work can never trip it.

2. `logLevel: "silent"` discarded `result.warnings` and there was no
   try/catch, so esbuild resolution problems escaped as an unhandled rejection
   printing esbuild's internal frames and `errors: [Getter/Setter]` instead of
   the messages. Silent is kept (as in the sibling) so stdout stays the single
   figure line CI quotes; warnings are now formatted to stderr and errors are
   re-thrown with esbuild's own formatted diagnostics.

3. An unbuilt dist died on a raw "Could not resolve" stack. A preflight on
   dist/headless.mjs now names `npx nx run @copilotkit/react-native:build`,
   and the catch adds the same hint when the entry specifier is what failed.

The measurement itself is untouched — same esbuild options, same synthetic
entry, same six symbols, same external list — and still reports 92.7 kB, so
comparability across PRs is preserved. A moved figure would have meant the
measurement changed rather than its guards.

Also adds the test hook RN lacked, mirroring react-core exactly:
scripts/__tests__/measure-headless.test.mjs under `node --test`, wired as
`test:scripts` and chained into `test`. Coverage targets the failure modes,
not the happy path. Both packages' vitest `include` globs are scoped to
`src/**`, so the .mjs test cannot collide with the jsdom setup — the reason
the sibling runs under node --test in the first place.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 23:05:01 +02:00