fix: replace svix with standardwebhooks to reduce install size (#969)#970
Conversation
svix (~4.2 MB) was pulled in solely for webhook signature verification via its `Webhook` class. That class is a thin wrapper that maps svix-* headers to webhook-* and delegates to standardwebhooks (~13 KB); the rest of svix is the full Svix platform API client (216 OpenAPI model files) that resend never uses, and being CommonJS it cannot be tree-shaken away by consumers. Depend on standardwebhooks directly instead. It is the same pure-JS HMAC implementation (keeps Cloudflare Workers / non-Node support) and produces identical signatures, so this is behavior-preserving with no public API change. A real, non-mocked round-trip test is added to guard the swap. Install size drops from ~5.0 MB to ~788 KB (~84% smaller). Closes #969
commit: |
There was a problem hiding this comment.
cubic analysis
No issues found across 5 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Linked issue analysis
Linked issue: DEV-848: Package size much bigger
| Status | Acceptance criteria | Notes |
|---|---|---|
| ✅ | Replace svix dependency with standardwebhooks in package.json | package.json now depends on standardwebhooks (1.0.0) instead of svix (1.92.2). |
| ✅ | Remove svix from lockfile / dependency graph | pnpm-lock.yaml no longer includes svix entries and lists standardwebhooks instead, showing svix was removed from the lockfile. |
| ✅ | Import and use standardwebhooks in code and map to standard webhook header names | webhooks.ts imports Webhook from standardwebhooks and passes 'webhook-id', 'webhook-timestamp', 'webhook-signature' to verify instead of the svix header names. |
| ✅ | Maintain public API (no signature change to Webhooks.verify / VerifyWebhookOptions) | The verify method signature remains verify(payload: VerifyWebhookOptions): WebhookEventPayload; changes are internal to the verification implementation and header names mapping is internal. |
| ✅ | Add/adjust tests to cover new implementation and real signature verification | Existing webhooks tests were updated to mock standardwebhooks and header names; a new real round‑trip test was added to verify actual signature generation/verification using the real library. |
| ✅ | Reduce on-disk install size compared to previous release | PR includes measured install-size results showing a reduction from ~5.0 MB to ~788 KB, and the dependency changes (removing svix) explain the size drop. |
Auto-approved: This change swaps the heavy svix dependency for its internal standardwebhooks library with identical behavior, reducing install size by over 80%, and the updated tests plus a new end-to-end verification confirm no functional regression.
Re-trigger cubic
verified locally using this version, and it works as expected! no public API changes and no regressions. cc @gabrielmfern |
Drop the file-wide `standardwebhooks` mock (only the verify test used it) and rewrite the verify test as a real sign + verify round-trip, plus a bad-signature case. Removes the separate webhooks-verify.spec.ts.
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Auto-approved: This PR replaces the heavy svix dependency (4.2 MB) with its own lightweight internal delegate standardwebhooks (44 KB), shrinking install size by ~84% while preserving the exact same public API and verification behavior, and the updated tests include a real cryptographic round-trip to ensure...
Re-trigger cubic
lucasfcosta
left a comment
There was a problem hiding this comment.
LGTM! Good catch using the same library Svix does :)
Problem
#969 reports that the installed package size grew dramatically. Measured on a clean install:
node_modulesresend@6.1.2resend@6.12.3(before this PR)The overwhelming majority is
svix(4.2 MB, 84% of the install), which is pulled in only for webhook signature verification insrc/webhooks/webhooks.ts.Why svix is so heavy (and why tree-shaking doesn't help)
Webhookclass resend uses is a 28-line wrapper that just mapssvix-*headers towebhook-*and delegates tostandardwebhooks(~13 KB).dist/modelsalone is 2.7 MB) plus 23 API resource clients — none of which resend uses."type": "commonjs"with nomodule/exports/sideEffects, and its barrelindex.jseagerlyrequire()s the entire API client, so it cannot be tree-shaken. (And tree-shaking never affects on-disk install size anyway —npm installalways downloads the whole tarball.)Change
Depend on
standardwebhooksdirectly instead ofsvix:package.json:svix@1.92.2→standardwebhooks@1.0.0src/webhooks/webhooks.ts: importWebhookfromstandardwebhooks; passwebhook-id/webhook-timestamp/webhook-signature(the standard header names svix mapped to internally).standardwebhooksis the same pure-JS HMAC-SHA256 implementation svix delegates to (keeps Cloudflare Workers / non-Node support) and produces identical signatures.No public API change
Webhooks.verify(...)andVerifyWebhookOptions(headers.{ id, timestamp, signature }) are unchanged.Result
Install size 5.0 MB → 788 KB (~84% smaller), verified via
npm pack+ clean install:Tests
webhooks.spec.tsto mockstandardwebhooksand assert thewebhook-*header names.webhooks-verify.spec.ts: a real, non-mocked round-trip test that signs a payload with the genuine library and assertsverify()returns the parsed event (and rejects a bad signature). The prior tests fully mocked verification, so the real crypto path was untested.pnpm test✅ 358 passed ·pnpm run build✅ ·pnpm run lint✅Closes #969
Summary by cubic
Replace
svixwithstandardwebhooksfor webhook signature verification to shrink install size from ~5.0 MB to ~788 KB (~84%) with no behavior or API changes. Addresses DEV-848 and #969; verification now useswebhook-*headers internally, and tests are consolidated intowebhooks.spec.tsusing a real sign+verify round trip plus a bad‑signature case (no mocks).Written for commit 014ee22. Summary will update on new commits. Review in cubic