Skip to content

Shrink install ~70 MB (bundle viem, trim package) and speed up startup ~5x (lazy-load heavy deps)#299

Merged
jancurn merged 2 commits into
mainfrom
claude/mcpc-bundle-size-c2p1lr
Jul 9, 2026
Merged

Shrink install ~70 MB (bundle viem, trim package) and speed up startup ~5x (lazy-load heavy deps)#299
jancurn merged 2 commits into
mainfrom
claude/mcpc-bundle-size-c2p1lr

Conversation

@jancurn

@jancurn jancurn commented Jul 9, 2026

Copy link
Copy Markdown
Member

Installing mcpc previously downloaded viem's ~70 MB dependency tree, and every command paid ~680 ms of startup importing dependencies used only by specific features. viem is now tree-shaken into a single ~650 KB bundle at build time and moved to devDependencies; heavy modules load lazily; the npm tarball stops shipping README media. Install shrinks from ~110 MB to ~36 MB (tarball ~6.9 MB → ~0.4 MB) and typical startup drops to ~150 ms.

  • All viem imports go through a boundary module (src/lib/x402/viem.ts) that esbuild bundles after tsc, with build-time guards against tree-shaking regressions; an eslint rule enforces the boundary
  • Lazy-loaded: x402/viem, the OAuth login stack (SDK auth), undici (skipped entirely without proxy env vars or --insecure), and ora spinners; removed an unused SDK value re-export that pulled zod schemas into every command
  • The release workflow now reports tarball/unpacked/full-install size next to the install instructions, compares with the latest npm version, and warns if the install grew >20%
  • .npmignore now excludes docs/ and dev config files

Verified by signing an x402 payment through the bundled code and checking the EIP-712 signature against an independent viem install; unit + e2e suites pass on node and bun.

https://claude.ai/code/session_01Ho8d2XkXtPXPgUnyGSntJb

claude added 2 commits July 8, 2026 14:44
viem (used only by the experimental x402 payment feature) was a regular
dependency, so every install downloaded its ~70 MB dependency tree, and
static imports in both the CLI and bridge entry points loaded it (including
~700 chain definitions) on every command.

- Route all viem imports through a boundary module (src/lib/x402/viem.ts)
  that esbuild tree-shakes into a self-contained ~650 KB file in dist after
  tsc; viem moves to devDependencies. Build-time metafile guards fail the
  build if tree-shaking regresses (websocket deps or chain barrel leaking in).
- Lazy-load x402 modules in the CLI and bridge so non-x402 commands no
  longer pay the import cost — startup drops from ~680 ms to ~350 ms.
- Stop shipping README media (docs/) and dev configs in the npm package:
  tarball shrinks from ~6.9 MB to ~0.4 MB.
- Enforce the viem import boundary with an eslint no-restricted-imports rule.

Verified end-to-end: x402 wallet init + exact-scheme EIP-712 signing through
the bundled code produces signatures that verify against an independent viem
install; unit tests (843) and e2e suites pass on node and bun (the 5 e2e
failures in the sandbox reproduce identically on unmodified main).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ho8d2XkXtPXPgUnyGSntJb
…startup

Release workflow now measures the tarball, unpacked, and full-install size of
the package being published, compares them with the latest version on npm in
the run summary, and emits a warning annotation when the install grew by more
than 20%, so an unexpectedly large release is caught before users notice.

Startup profiling showed most of the ~680 ms command startup was import cost
of dependencies used only by specific commands, now loaded lazily:

- The MCP SDK's zod schemas loaded on every command through a single unused
  value re-export (LATEST_PROTOCOL_VERSION) in lib/types.ts — removed.
- The OAuth login stack (oauth-flow, client-credentials, SDK auth) is imported
  inside the login paths instead of statically by commands/auth.ts.
- undici is skipped entirely when no proxy env vars are set and --insecure is
  not used; native fetch behaves identically without it.
- ora spinners load at their two call sites.

Typical command startup drops from ~680 ms to ~150 ms (~260 ms when a proxy
is configured, since undici must load). Verified with unit tests and the
basic/sessions e2e suites on node plus a bun smoke test; the only failures
are pre-existing sandbox-environment ones that reproduce on main.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ho8d2XkXtPXPgUnyGSntJb
@jancurn jancurn changed the title Bundle viem into a single artifact to keep it as devDependency Shrink install ~70 MB (bundle viem, trim package) and speed up startup ~5x (lazy-load heavy deps) Jul 9, 2026
@jancurn
jancurn merged commit 280ccf0 into main Jul 9, 2026
6 checks passed
@jancurn
jancurn deleted the claude/mcpc-bundle-size-c2p1lr branch July 9, 2026 09:37
jancurn added a commit that referenced this pull request Jul 10, 2026
The install-size report added in #299 only went to the workflow run
summary, so the release page itself (e.g. v0.4.1-beta.0) showed no size
info. The script now also exposes the report as a step output, and both
the pre-release and release steps embed it in the release body right
under the install instructions.

- `report-install-size.mjs` writes the markdown report to
`$GITHUB_OUTPUT` (multiline `report` output) in addition to stdout and
the run summary
- The two inline invocations in the version-bump steps are replaced by
one dedicated `Report install size` step shared by both release types
- Both `action-gh-release` bodies append `${{
steps.install-size.outputs.report }}`

Refs #299

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01Ho8d2XkXtPXPgUnyGSntJb

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Ho8d2XkXtPXPgUnyGSntJb)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants