perf(build): cut CLI startup time - #2181
Conversation
…ion React, and enabling the V8 compile cache @smithy/core was pinned at 3.29.3 while every @aws-sdk client wanted ^3.33.3, so bun nested 51 private copies and the bundler inlined all of them. Bumping the pin shrinks the bundle from 9.2 MB to 5.6 MB. The bundle carried React's development build because NODE_ENV was never defined at bundle time. Both builds now define it as production. dist/index.js is now a four-line loader that calls enableCompileCache() before importing the bundle (dist/main.js). V8 only caches modules loaded after the call, so a single-file bundle cannot cache itself. The loader is a no-op below Node 22.1. `agentcore --version`, median of 7 runs: Node 20: 620 ms -> 475 ms Node 24: 478 ms -> 407 ms binary: 652 ms -> 442 ms The remaining 140-180 ms is the telemetry HTTPS flush at exit, left for a follow-up.
|
Claude Security Review: no high-confidence findings. (run) |
There was a problem hiding this comment.
AgentCore Harness Review
Verdict: Looks good
Nice, tight change. Three things bundled together, all reasonable:
-
NODE_ENV=productiondefine (scripts/build.ts) — necessary for React/Ink to select their production build. Verified nothing undersrc/readsprocess.env.NODE_ENV, so this token replacement has no unintended side effects on our own code. Applied to bothbundleandcompile, which is correct. -
V8 compile-cache loader (
scripts/build.ts+src/index.ts) — the split intodist/index.js(loader with shebang) →dist/main.js(bundle) is the right shape:enableCompileCache()must run before the modules you want cached, and the dynamicawait import("./main.js")runs after. Sanity-checked:resolveAssetsRoot()insrc/core/project/source.tsusesimport.meta.urlfrom the bundle, sodist/main.js/../assetsstill resolves correctly.- No downstream references to
dist/index.jsother than thebin/mainfields inpackage.json, which still point at a valid ESM entry. type: module+ ESM loader + ESM bundle line up.
-
@smithy/corebump3.29.3→^3.33.3— onlyServiceExceptionandWaiterStateare imported from@smithy/core/client, both stable. Deduping the huge block of nested overrides inbun.lockis a nice side effect.
No test or telemetry changes needed for a build-time perf tweak. LGTM.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## refactor #2181 +/- ##
=========================================
Coverage 97.08% 97.08%
=========================================
Files 536 536
Lines 36979 36979
=========================================
Hits 35901 35901
Misses 1078 1078 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Claude Security Review: no high-confidence findings. (run) |
Summary
Profiling
agentcore --versionshowed ~10 ms of actual work inside ~620 ms of wall time. This PR removes the three largest self-inflicted costs in the build.@smithy/core. package.json pinned it at3.29.3while every@aws-sdk/client-*wanted^3.33.3, so bun nested 51 private copies and the bundler inlined all of them (34 copies ofhttpAuthSchemeMiddlewarein the bundle). Bumped to^3.33.3. Bundle: 9.2 MB → 5.6 MB.NODE_ENVwas never defined at bundle time, so both the npm bundle and the compiled binary carried React's development build (runWithFiberInDEVetc.). Both builds nowdefineit asproduction.dist/index.jsis now a four-line loader that callsmodule.enableCompileCache()and imports the bundle atdist/main.js. V8 only caches modules loaded after the call, so a single-file bundle cannot cache its own compilation. No-op on Node < 22.1. Bun inlines relative imports even when markedexternal, so the build script writes the loader directly.bin,main,node dist/index.js, and the Makefile/README references are unchanged:dist/index.jsis still the entry, it just delegates.Measurements
Artifact size:
dist/main.js)agentcore --version, median of 7 runs, telemetry enabled:With
AGENTCORE_TELEMETRY_DISABLED=1(isolates startup from the exit flush): Node 24 311 ms → 246 ms, binary → 300 ms.Not in this PR
OtelHistogramSink.shutdown) is now the largest remaining cost. Needs a design decision (spool-and-forward vs. detached flusher); follow-up.inkandyoga-layoutuse top-level await.Verification
bun test: 2803 pass, 0 failbun run typecheck,bun run lint:check,prettier --check: cleanbun run buildandbun run compile:darwin-arm64: both artifacts run--versionand render the interactive TUI (root menu, harness submenu) with the production React buildos.tmpdir()/node-compile-cacheon Node 24