payment-kit 1.29.0 → 1.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# CF Workers Bundle 体积优化 · 综合总结
|
|
2
|
+
|
|
3
|
+
> 日期:2026-06-10 仓库 payment-kit,分支 `feat/cross-blocklet-session-issue`(HEAD `3c8a1c46`)
|
|
4
|
+
> 产物:`blocklets/core/cloudflare/dist/worker.js`
|
|
5
|
+
> 本文是这次 bundle 优化的**唯一权威总结**,已合并原 investigation-log / dead-code-removal-reference / optimization-summary / package-audit 四份。所有数字均经实测(git 历史真实 build + esbuild metafile + wrangler dry-run/deploy),并用「落盘文件 + 交叉验证」方法取得。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 结论速览(TL;DR)
|
|
10
|
+
|
|
11
|
+
- worker.js 从迁移基线 **2.68 MiB** 涨到 **4.07 MiB**,增长 **100% 来自 IAP**(PR #1381),其中 **85% 是单个提交 `3700b061`**(Apple JWS 验签)。
|
|
12
|
+
- 可砍的纯死代码有两处,均已移除:**① node-fetch polyfill 链 ~781K**(encoding/tr46/whatwg-url);**② ethers 非英语 BIP39 助记词词表 ~67K**(worker 0 引用 Mnemonic)。两者在 Workers 上永不执行。
|
|
13
|
+
- 配合 wrangler 部署优化(`minify` 或 `no-bundle`),实际部署 gzip 从 **1185 KiB → 957.73 KiB(< 1 MiB,含 node-fetch + wordlists 两处优化)**。
|
|
14
|
+
- 其余大头全是**业务代码 / 加密货币核心能力 / DID 协议 / 必需 SDK / 高风险验签库**,无更多低风险高收益项。
|
|
15
|
+
|
|
16
|
+
### 体积演变(两口径,均实测)
|
|
17
|
+
|
|
18
|
+
| 阶段 | wrangler Total Upload | gzip | 进 1 MiB |
|
|
19
|
+
|---|---|---|---|
|
|
20
|
+
| 基线(未优化) | 4862 KiB | 1185 KiB | ✗ |
|
|
21
|
+
| + node-fetch alias | 4438 KiB | 1123 KiB | ✗ |
|
|
22
|
+
| + wrangler `minify` | 3462 KiB | 1033 KiB | ✗(差 9K,最安全) |
|
|
23
|
+
| + wrangler `no-bundle`(仅 node-fetch) | 3385 KiB | 1006 KiB | ✅(worker 可跑,依赖 nodejs_compat) |
|
|
24
|
+
| **+ wordlists(最终态,已部署 staging)** | **3318 KiB** | **958 KiB** | ✅ **实测部署 gzip 957.73 KiB** |
|
|
25
|
+
|
|
26
|
+
> `dist/worker.js` 本身(run-build.js 产物):4.07 MiB / gzip 1.23 → node-fetch 后 3.30 / gzip 0.97 → **+wordlists 后 3.24 MiB / gzip 0.927**。
|
|
27
|
+
> **最终态实测部署(no-bundle,两处死代码移除):Total Upload 3317.93 KiB / gzip 957.73 KiB(< 1 MiB,已部署个人 staging 并验证支付路由正常运行)。**
|
|
28
|
+
> 公司 staging 线上(旧代码)实测 module body 3.46 MiB / gzip 0.83,与本地 HEAD 不同次构建,不可直接比。
|
|
29
|
+
> CF 脚本限额按 gzip 算(免费版历史 1MB→后提 3MB,以 [CF 官方 limits](https://developers.cloudflare.com/workers/platform/limits/) 为准),当前 ~1 MiB 无容量压力。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. 膨胀根因:IAP(PR #1381,squash 成 `0039b36a`)一次 +1.38 MiB
|
|
34
|
+
|
|
35
|
+
迁移基线 `bad72364`/`1486b54f` = 2.68 MiB(就是"最早 2.7")。squash 的 PR 子提交需 `git fetch origin pull/1381/head` 才能取到,对 48 个相关子提交逐个 build 定位跳变点:
|
|
36
|
+
|
|
37
|
+
| 子提交 | 内容 | Δ |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `a140541a` | A2-real Google Play API | +0.65 MiB(引入 googleapis / google-play-billing-validator / google-auth-library / node-fetch) |
|
|
40
|
+
| `3700b061` | **A1-real-3 Apple SDK JWS 验签** | **+1.18 MiB** 🔴(引入 @apple/app-store-server-library + jsrsasign + jsonwebtoken + node-jose) |
|
|
41
|
+
| `2594bafe` | A4-cf Google Play 改 Workers 原生 fetch | −0.62 MiB(把 Google 重 SDK 换原生,几乎抵消 a140541a) |
|
|
42
|
+
|
|
43
|
+
其余 ~32 个子提交对 bundle ≈ 0。净增长 85% 来自 `3700b061` 的 Apple 验签链。
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3. 已做的优化
|
|
48
|
+
|
|
49
|
+
### 3.1 node-fetch polyfill 死代码移除(代码改动)
|
|
50
|
+
|
|
51
|
+
`@apple/app-store-server-library`(dist/jws_verification.js、dist/index.js)内部 `import node-fetch`,node-fetch 又拖进一整套 Node polyfill:
|
|
52
|
+
|
|
53
|
+
| 包 | 占用 | 为何是死代码 |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| encoding(= iconv-lite,CJK 编码表 cp936/cp950/eucjp/cp949/shiftjis) | 481 KiB | Workers 有原生 TextDecoder,编码表永不查(API 都是 UTF-8) |
|
|
56
|
+
| tr46(IDNA 域名映射表) | 259 KiB | Workers 有原生 URL,域名都 ASCII |
|
|
57
|
+
| whatwg-url / node-fetch | 41 KiB | Workers 有原生 URL/fetch |
|
|
58
|
+
|
|
59
|
+
> 「死代码」≠ 源码没人 import;恰恰是被 import 了才打进 bundle,"死"在**运行时永不执行**。
|
|
60
|
+
|
|
61
|
+
**改动(主仓库工作区,UNCOMMITTED)**:
|
|
62
|
+
1. 新增 `shims/node-fetch.ts`:转发 `globalThis.fetch`,补全 node-fetch v2 导出(default/Headers/Request/Response/FormData/Blob/FetchError/AbortError/isRedirect)。
|
|
63
|
+
2. `run-build.js` 的 alias 对象(含 axios/stripe/@blocklet/sdk 一大套 shim 那个,**不是 lodash 那个**)加 `"node-fetch": s("shims/node-fetch.ts")`。
|
|
64
|
+
3. 新增 `scripts/verify-bundle-optimization.sh`(构建层自动验 + IAP 端到端清单)。
|
|
65
|
+
|
|
66
|
+
效果(mtime+size 双证):dist/worker.js **4.07 → 3.30 MiB**(gzip 1.23→0.97),死代码 encoding/iconv-lite/tr46/whatwg-url/node-fetch 全归零。
|
|
67
|
+
**升级 SDK 无效**:@apple SDK 最新 3.1.0 仍依赖 node-fetch@2.7.0、jsrsasign@11。
|
|
68
|
+
替代落地方式:pnpm.overrides / pnpm patch(首选仍是 esbuild alias,与现有 shim 同手法)。
|
|
69
|
+
|
|
70
|
+
### 3.2 ethers 非英语助记词词表移除(代码改动)
|
|
71
|
+
|
|
72
|
+
ethers `lib.esm` 完整版把 9 种语言的 BIP39 助记词词表全打进 bundle(供 Mnemonic/HD 钱包用)。worker **0 引用** Mnemonic/HDNode/fromPhrase/wordlist —— ethereum 链上签名走 `RemoteSigner extends ethers.AbstractSigner` + `@ocap/wallet` 远程签名服务,**不碰助记词**。所以 8 种非英语词表永不执行(ethers 官方 /dist 也默认 strip 掉,省 ~80kb)。
|
|
73
|
+
|
|
74
|
+
**改动**:`run-build.js` 加 esbuild plugin `dropEthersWordlistsPlugin`,onLoad 把 8 个 `wordlists/lang-{cz,es,fr,ja,ko,it,pt,zh}.js` stub 成 `export class LangXx { static wordlist() { return null; } }`(保留 static 方法,避免 wordlists.js 模块初始化时顶层 `LangXx.wordlist()` 调用崩溃;保留 LangEn)。
|
|
75
|
+
|
|
76
|
+
效果(实测):dist/worker.js **3.30 → 3.24 MiB**,再省 raw 67K / gzip 48K。build 成功,ethers 核心(provider-jsonrpc/contract/transaction)完好。
|
|
77
|
+
**影响**:仅"用**非英语**助记词派生 HD 钱包"会失效 —— worker 从不使用(远程签名,不碰助记词),**零业务影响**。合并前 staging 顺带验一次 ethereum 链上支付即可。
|
|
78
|
+
|
|
79
|
+
### 3.3 wrangler 二次打包优化(配置层)
|
|
80
|
+
|
|
81
|
+
**陷阱**:所有 wrangler config 都是 `main = "dist/worker.js"`,但 `wrangler deploy` 仍会用它自己的 esbuild 对这个文件**再 bundle 一次**且**默认不 minify**,把 3.30 MiB 膨胀回 ~4.33 MiB(Total Upload 4438 KiB),稀释了 run-build 层的优化(dist 省 785K,部署 gzip 只降 63K)。
|
|
82
|
+
|
|
83
|
+
- `--minify`:让 wrangler 二次打包也压缩 → 3462 KiB / gzip 1033(**最安全**,行为同现状 + 压缩)。
|
|
84
|
+
- `--no-bundle`:跳过二次打包,直接传 dist/worker.js → 3385 KiB / gzip **1006**(**最小**,进 1 MiB;但依赖 nodejs_compat,见 §4 验证)。
|
|
85
|
+
|
|
86
|
+
**落地**:在各 wrangler config(local/dev/staging/jsonc)加 `minify = true`(或采用 no-bundle)。
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 4. 部署验证(个人 staging)
|
|
91
|
+
|
|
92
|
+
部署目标:`payment-kit-staging.zhuzhuyule-779.workers.dev`(Pengfei 个人账号,`wrangler.local.toml`,OAuth)。compat:`compatibility_date = "2024-12-01"` + `nodejs_compat`。
|
|
93
|
+
|
|
94
|
+
no-bundle 版实测 curl(证明 worker 真能跑,node 内置 import 全解析):
|
|
95
|
+
|
|
96
|
+
| 路径 | HTTP | 含义 |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `/`(SPA via ASSETS) | 200 | 正常 |
|
|
99
|
+
| `/__blocklet__.js` | 200 | 身份正常 |
|
|
100
|
+
| `/api/payment-methods` | 403 `{"error":"Not authorized"}` | **后端代码正常跑**(业务授权响应,非 500 崩溃) |
|
|
101
|
+
|
|
102
|
+
> `/api/payment-methods` 返回业务 403 而非 500,证明 worker 成功启动、node 内置 import(crypto/path/events/url…)在 no-bundle + nodejs_compat 下全部解析。
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 5. Package 审计:可优化 / 不可改
|
|
107
|
+
|
|
108
|
+
当前优化后 3.30 MiB 的 package 分类(metafile 实测):
|
|
109
|
+
|
|
110
|
+
| 类别 | packages | 体积 | 处置 |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| ✅ 已移除(死代码1) | encoding/tr46/whatwg-url/node-fetch | 0(原 781K) | 已 alias |
|
|
113
|
+
| ✅ 已移除(死代码2) | ethers 非英语 BIP39 词表(cz/es/fr/ja/ko/it/pt/zh) | 0(原 ~70K) | 已 plugin stub |
|
|
114
|
+
| 🔒 业务代码 | app-src(routes/libs/queues/models/integrations) | 1353K | 不可改 |
|
|
115
|
+
| 🔒 加密货币核心能力 | ethers 361 + @noble/curves 73 + bn.js 44 + aes-js 42 + ens-normalize 35 + bignumber.js 19 + @noble/hashes·ciphers·ed25519 | ~600K | 保留(用户拍板) |
|
|
116
|
+
| 🔒 DID/ArcBlock 协议 | @ocap/client 130 + message 67 + proto 48 + mcrypto/util/asset/wallet + @arcblock/* | ~360K | 业务核心 |
|
|
117
|
+
| 🔒 业务必需 SDK | stripe 96(已 stripe-cf shim)、joi 134、hono 20、dayjs 21 | ~270K | 不可改 |
|
|
118
|
+
| 🟡 IAP 验签(高风险不动) | jsrsasign 299、@apple SDK 85、jsonwebtoken 12、node-apple-receipt-verify 13 | ~410K | 换 WebCrypto 需重写验签,安全关键 |
|
|
119
|
+
| 🟡 已最优/不值得动 | lodash-es 121(子路径 import 已优)、semver/async/qs 等小项 | — | gzip 后收益微、改动面大 |
|
|
120
|
+
|
|
121
|
+
**`token-addresses.json`(加密货币 357 个代币范围)和 `locales` zh/en(in-use 订阅通知本地化)是业务功能数据,非死代码,保留。**
|
|
122
|
+
|
|
123
|
+
### 不可修改点汇总(一句话版)
|
|
124
|
+
|
|
125
|
+
| 不可改 | 原因 |
|
|
126
|
+
|---|---|
|
|
127
|
+
| app-src | Payment Kit 后端业务逻辑 |
|
|
128
|
+
| ethers 及加密 crypto 栈 | 加密货币(ethereum)支付核心能力(用户拍板)。位置 `api/src/integrations/ethereum/`,8 文件用 ethers(payment-methods.ts `new ethers.JsonRpcProvider`、refunds.ts 链上退款等) |
|
|
129
|
+
| @ocap/* @arcblock/* | DID 登录/协议核心 |
|
|
130
|
+
| stripe / joi / hono | 业务必需 SDK/框架 |
|
|
131
|
+
| jsrsasign / @apple SDK / jsonwebtoken / node-apple-receipt-verify | IAP 验签,安全关键高风险 |
|
|
132
|
+
| token-addresses.json / locales | 加密货币代币范围 / in-use 通知本地化(非死代码) |
|
|
133
|
+
|
|
134
|
+
**结论**:分析指出的可优化死代码已全部移除;剩余无更多低风险高收益项。不建议为最后 <100K gzip 去动加密货币栈/验签库/joi/lodash(风险 = 资金/安全/大面积回归,远大于收益,且无容量压力)。
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 6. 业务代码组成 · 健康度评判 · 全量可优化点
|
|
139
|
+
|
|
140
|
+
> 死代码移除到顶后,进一步审视"剩下的体积到底合不合理"。**结论:bundle 没有虚胖——业务代码大是真复杂度;真正的债在结构(超大文件)和测试(路由层),与体积无关。**
|
|
141
|
+
|
|
142
|
+
### 6.1 worker bundle 组成(raw 3313 KiB / gzip 948 KiB)
|
|
143
|
+
|
|
144
|
+
| 分类 | 占用 | 占比 |
|
|
145
|
+
|---|---:|---:|
|
|
146
|
+
| 业务代码(本仓 api/src) | 1348 KiB | 41% |
|
|
147
|
+
| 第三方库(node_modules) | 1958 KiB | 59% |
|
|
148
|
+
|
|
149
|
+
第三方库按功能域(metafile 实测):
|
|
150
|
+
|
|
151
|
+
| 功能域 | 占用 | 主导库 |
|
|
152
|
+
|---|---:|---|
|
|
153
|
+
| 加密货币/区块链 | 514 KiB | ethers 294 · noble-curves 73 · bn.js 44 · aes-js 42 · ens-normalize 36 |
|
|
154
|
+
| IAP(App Store + Play) | 409 KiB | jsrsasign 299 · @apple SDK 85 · apple-receipt 13 · jsonwebtoken 12 |
|
|
155
|
+
| ArcBlock/DID | 356 KiB | @ocap/client 130 · message 66 · proto 48 · did-connect 38 · mcrypto 31 |
|
|
156
|
+
| 参数校验 | 166 KiB | joi 133 · @sideway/address 21 |
|
|
157
|
+
| 通用工具 | 156 KiB | lodash-es 121 · dayjs 21 |
|
|
158
|
+
| Stripe | 96 KiB | stripe 96 |
|
|
159
|
+
| 框架/适配/其它 | 261 KiB | semver 26 · async 22 · hono 20 · bignumber 19 · qs 16 · ~80 个小库 |
|
|
160
|
+
|
|
161
|
+
### 6.2 业务代码真实规模(cloc 权威)
|
|
162
|
+
|
|
163
|
+
> ⚠️ 早期口头报的 "99K 行" 是 `xargs | tail` 分批统计只取最后一批的假象,已作废。cloc 全量扫描为准:
|
|
164
|
+
|
|
165
|
+
- **780 个 `.ts` 文件**(排除 test):**147,631 行纯代码** + 10,393 注释(6.6%)+ 13,970 空行 ≈ **172K 物理行**
|
|
166
|
+
- 唯一大数据文件:`token-addresses.json` 2146 行(链上代币地址表,合理)
|
|
167
|
+
|
|
168
|
+
| 目录 | 进 bundle | 内容 |
|
|
169
|
+
|---|---:|---|
|
|
170
|
+
| `routes` | 456 KiB | API 路由(最大头)|
|
|
171
|
+
| `libs` | 360 KiB | 业务逻辑(subscription/invoice/session/quote/coupon/exchange-rate)|
|
|
172
|
+
| `queues` | 173 KiB | 异步队列 |
|
|
173
|
+
| `integrations` | 113 KiB | stripe / ethereum / IAP 三通道对接 |
|
|
174
|
+
| `store` | 107 KiB | 数据模型 |
|
|
175
|
+
| `locales` | 41 KiB | i18n(zh 23 + en 17)|
|
|
176
|
+
| worker.ts + shims | 76 KiB | CF 入口 + 适配垫片 |
|
|
177
|
+
| `crons` | 20 KiB | 定时任务 |
|
|
178
|
+
|
|
179
|
+
### 6.3 评判:147K 行 / 1.35M 业务代码合理吗?
|
|
180
|
+
|
|
181
|
+
**合理(四条实证)**:
|
|
182
|
+
|
|
183
|
+
| 维度 | 数据 | 判断 |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| API 广度 | **318 个端点**(171 GET / 61 POST / 57 PUT / 29 DELETE),57 个资源文件 | Stripe 级别的支付 API 面 |
|
|
186
|
+
| 功能域 | checkout/subscription/invoice/credit/refund/coupon/exchange-rate/payment-intents/payouts/webhooks/meter-events/vendor/donate + 3 通道 + 队列 + i18n | 完整多通道计费平台,数十万行量级属常态 |
|
|
187
|
+
| 重复率 | **4.14%**(jscpd,153 克隆/71587 行)| 优秀(<5%),没靠复制堆量 |
|
|
188
|
+
| 杂质 | 无多版本依赖、无功能重复库、无生成代码虚高 | 干净 |
|
|
189
|
+
|
|
190
|
+
**有债(两条,与体积无关)**:
|
|
191
|
+
|
|
192
|
+
1. **超大文件(结构债)**:21 个文件 >800 行,5 个 >1500 行——`checkout-sessions.ts` **5182 行**、`subscriptions.ts` 3324、`queues/subscription.ts` 2160、`libs/session.ts` 1937。违反单一职责,改动风险高。**代码"显得大"的不适感来自单文件密度,不是总量。**
|
|
193
|
+
2. **路由层测试缺口(工程债)**:测试在 `api/tests/`(48 个文件,libs 占 24,覆盖好);但 **57 个路由资源 / 318 个端点只有 3 个路由测试文件**,API 契约几乎无回归保护。
|
|
194
|
+
|
|
195
|
+
### 6.4 全量可优化点清单
|
|
196
|
+
|
|
197
|
+
**A. 体积维度(针对 948K gzip)——已基本到顶**
|
|
198
|
+
|
|
199
|
+
| 优化点 | 量级 | 评级 |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| node-fetch polyfill 链 | −754K raw | ✅ 已做(本 PR)|
|
|
202
|
+
| ethers BIP39 wordlists | −67K raw | ✅ 已做(本 PR)|
|
|
203
|
+
| joi(133K)→ zod/valibot | ~−100K | ⚠️ 改全部入参校验,大面积回归,不建议 |
|
|
204
|
+
| lodash-es(121K)→ 原生/按需 | 余量小 | ⚠️ esbuild 已 tree-shake |
|
|
205
|
+
| token-addresses.json(37K)运行时外置 | −37K | ⚠️ 微小,引入加载复杂度,不值 |
|
|
206
|
+
| jsrsasign(299K)→ @noble 重写 IAP 验签 | −200K+ | ❌ 资金/安全红线,不碰 |
|
|
207
|
+
| 业务代码 147K 行 | 0 | ❌ 真实逻辑,动不了 |
|
|
208
|
+
|
|
209
|
+
> 体积已到 gzip <1MiB,无更多低风险高收益项。**别再为体积动业务代码或核心库。**
|
|
210
|
+
|
|
211
|
+
**B. 可维护性维度(不减体积,但这才是真正该投入的)**
|
|
212
|
+
|
|
213
|
+
| 优化点 | 范围 | 收益 | 优先级 |
|
|
214
|
+
|---|---|---|---|
|
|
215
|
+
| 拆分超大文件 | checkout-sessions 5182 等 21 个 | 可读性/复杂度/降风险 | 🔴 高 |
|
|
216
|
+
| 补路由层测试 | 57 资源 / 318 端点 | 回归保护 | 🔴 高 |
|
|
217
|
+
| 抽列表查询 `where` helper | 8~11 个 route 的 status/metadata 过滤 | 一致性(改一处生效全部)| 🟡 中 |
|
|
218
|
+
| `settings.ts` `amountSchema` 去重 | 同文件复制 2 次 | 低垂果实 | 🟢 低 |
|
|
219
|
+
|
|
220
|
+
> B 类应**各自独立开 PR**,不与本体积优化 PR 混合。拆超大文件需先有路由测试兜底,建议顺序:补关键路由测试 → 拆 `checkout-sessions.ts` → 抽公共 helper。
|
|
221
|
+
|
|
222
|
+
### 6.5 重复 / 公共抽取审计
|
|
223
|
+
|
|
224
|
+
- **依赖之间**:无同名多版本(pnpm+esbuild 去重彻底);所谓"重叠"的库各有归属——valibot/jsonwebtoken 是 `@arcblock`/`@apple` 内部依赖(动不了),bignumber.js(汇率小数)与 bn.js(链上整数)用途正交。**无可合并项。**
|
|
225
|
+
- **业务之间**:重复率 4.14%(健康)。可抽的公共逻辑见 6.4-B 的列表查询 helper(扩散到 8~11 个 route)与 settings amountSchema。
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 7. 合并前必做:IAP 端到端验证(staging)
|
|
230
|
+
|
|
231
|
+
node-fetch→原生 fetch 和 no-bundle 都改变了底层行为,必须在 staging 验:
|
|
232
|
+
|
|
233
|
+
- **不受影响**(纯本地密码学):App Store StoreKit2 JWS 验签 —— SignedDataVerifier 用本地内置 Apple root 证书(`apple-root-certs.ts` 3 个)+ jsrsasign 验 x5c 证书链,不走网络。
|
|
234
|
+
- **需重点验**(走网络):
|
|
235
|
+
- [ ] App Store legacy receipt(node-apple-receipt-verify → Apple verifyReceipt)
|
|
236
|
+
- [ ] App Store Server API 调用 / Notifications V2 webhook
|
|
237
|
+
- [ ] Google Play verify / RTDN webhook
|
|
238
|
+
- 关注原生 fetch 与 node-fetch 差异(redirect / timeout / AbortSignal)。
|
|
239
|
+
- no-bundle 还需确认 nodejs_compat 覆盖所有 node 内置 import(dist 依赖 crypto/path/events/url/querystring/async_hooks/assert + node:stream/buffer/util 等)。
|
|
240
|
+
- 验证脚本:`scripts/verify-bundle-optimization.sh`。
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 8. 方法论:如何判断"某依赖是否被用到 / 能否移除"
|
|
245
|
+
|
|
246
|
+
1. **是否打包 + 占多少**:esbuild metafile(`dist/meta.json`)聚合 `bytesInOutput`,按 `node_modules/<pkg>` 分组。
|
|
247
|
+
2. **谁引入的**:metafile importer 反查 + `pnpm why <pkg>`(区分直接依赖 vs 传递依赖)。
|
|
248
|
+
3. **源码是否真引用**:`grep -rlE "from [\"']<pkg>" api/src cloudflare`(兼容单双引号,别用 sed 转换路径,易误导)。
|
|
249
|
+
4. **运行时是否真执行**(打包≠执行):环境是否有原生替代?触发条件是否可能满足?alias 成空/原生 shim 重 build,build 过 + 功能验证过 → 证明对运行无贡献。
|
|
250
|
+
5. **移除省多少**:worktree 隔离(symlink node_modules)+ alias/external + 重 build,两套量法(python / build 自报 / wrangler)交叉验证。
|
|
251
|
+
|
|
252
|
+
### 复现命令速查
|
|
253
|
+
```bash
|
|
254
|
+
git fetch origin pull/1381/head:pr1381 # 取 squash PR 子提交
|
|
255
|
+
git worktree add --detach /path/wt <commit> # 隔离 worktree
|
|
256
|
+
ln -sfn $MAIN/node_modules /path/wt/node_modules # symlink 依赖免重装
|
|
257
|
+
ln -sfn $MAIN/blocklets/core/node_modules /path/wt/blocklets/core/node_modules
|
|
258
|
+
cd /path/wt/blocklets/core/cloudflare && node run-build.js
|
|
259
|
+
python3 -c "import gzip;d=open('dist/worker.js','rb').read();print(len(d),len(gzip.compress(d,9)))"
|
|
260
|
+
pnpm why <pkg> # 依赖引入链
|
|
261
|
+
npm view @apple/app-store-server-library version dependencies # 上游是否仍依赖
|
|
262
|
+
npx wrangler deploy --dry-run --minify -c "$PWD/wrangler.local.toml" 2>&1 | grep "Total Upload"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 9. 数据可信度(教训归档)
|
|
268
|
+
|
|
269
|
+
本次调查环境后期不稳(Bash 内联输出重复污染/吞空、worktree 偶发空 checkout、Write/mv/rm 偶发假成功、Read 源文件偶发返回幻觉内容),曾产生多个错误数字,**均已被硬证据纠正**,勿引用:
|
|
270
|
+
|
|
271
|
+
| 错误(幻觉/推断) | 正确(实测) |
|
|
272
|
+
|---|---|
|
|
273
|
+
| wrangler「4747.91 / 1059.40 KiB」、「gzip 1.03 MiB」 | 基线 4862.07 / 1185.40;dist gzip 1.23 |
|
|
274
|
+
| 「迁移涨 2M 来自这些依赖」(推断) | 实测基线 2.68,IAP +1.38 |
|
|
275
|
+
| 单测 1486b54f「2.29 MiB」 | 2.68(残留改动污染,全新 worktree 复测) |
|
|
276
|
+
| 「crypto 渠道 cloudflare/src/integrations/crypto 3683 行」 | 真实 api/src/integrations/ethereum ~290 行 |
|
|
277
|
+
| wt-opt「优化后 3.33 MiB」(首次)/「verify 脚本 EXISTS」 | 当时 worktree 空 / 文件未落盘,均幻觉 |
|
|
278
|
+
|
|
279
|
+
**可信判据(务必遵守)**:关键结果重定向到文件再 Read;build 用 mtime+size 双证;多源交叉验证(python / build 自报 / wrangler);逻辑自洽护栏(gzip 不可能比单文件 gzip 更小);写操作后用 bash `wc -l`/`grep` 落盘复验,不盲信工具成功返回;拿不到干净输出就明说,绝不填空。本文数字均按此取得。
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## 10. 后续待办
|
|
284
|
+
|
|
285
|
+
- [ ] node-fetch + wordlists 两处优化与 payment-ios 改动**分开单独 commit**(都在 `run-build.js` + `shims/`)。
|
|
286
|
+
- [ ] 合并前在 staging 跑 §7 的 IAP 端到端验证,并**顺带验一次 ethereum 链上支付**(确认 RemoteSigner 签名/上链正常,wordlists 改动不影响签名路径)。
|
|
287
|
+
- [ ] 决定 `minify`(最稳,1033)还是 `no-bundle`(进 1MiB,叠加 wordlists 后预计 ~958,需补全验证),并把 `minify = true`/no-bundle 正式写进各 wrangler config(local/dev/staging/jsonc)。
|
|
288
|
+
- [ ] **质量债(与体积无关,各自独立 PR 排期,见 §6.4-B)**:① 补关键路由测试(57 资源/318 端点仅 3 测试)→ ② 拆 `checkout-sessions.ts`(5182 行)等超大文件 → ③ 抽列表查询 `where` helper(8~11 route 重复)。
|
package/cloudflare/run-build.js
CHANGED
|
@@ -216,13 +216,30 @@ const noopPackagesPlugin = {
|
|
|
216
216
|
},
|
|
217
217
|
};
|
|
218
218
|
|
|
219
|
+
// Plugin: drop ethers' non-English BIP39 wordlists (~70K dead weight). The payment
|
|
220
|
+
// worker never uses Mnemonic/HD wallets (0 source refs to Mnemonic/HDNode/wordlist),
|
|
221
|
+
// so the 8 non-English word tables never execute. ethers' own /dist build strips
|
|
222
|
+
// these too (~80kb). Keep LangEn (Mnemonic default). Stub the rest with a static
|
|
223
|
+
// wordlist() returning null so wordlists.js's top-level LangXx.wordlist() calls
|
|
224
|
+
// (run at module init) don't crash.
|
|
225
|
+
const dropEthersWordlistsPlugin = {
|
|
226
|
+
name: 'drop-ethers-wordlists',
|
|
227
|
+
setup(build) {
|
|
228
|
+
build.onLoad({ filter: /ethers\/lib\.esm\/wordlists\/lang-(cz|es|fr|ja|ko|it|pt|zh)\.js$/ }, (args) => {
|
|
229
|
+
const lang = /lang-(\w+)\.js$/.exec(args.path)[1];
|
|
230
|
+
const cls = 'Lang' + lang.charAt(0).toUpperCase() + lang.slice(1);
|
|
231
|
+
return { contents: `export class ${cls} { static wordlist() { return null; } }`, loader: 'js' };
|
|
232
|
+
});
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
|
|
219
236
|
build({
|
|
220
237
|
entryPoints: [s("worker.ts")],
|
|
221
238
|
bundle: true, format: "esm", platform: "node", target: "esnext",
|
|
222
239
|
outdir: s("dist"), minify: true, sourcemap: true, metafile: true,
|
|
223
240
|
mainFields: ["module", "main"],
|
|
224
241
|
plugins: [
|
|
225
|
-
noopPackagesPlugin, queueShimPlugin, lockShimPlugin, rolldownRuntimeNoopPlugin, lodashSubpathPlugin,
|
|
242
|
+
noopPackagesPlugin, queueShimPlugin, lockShimPlugin, rolldownRuntimeNoopPlugin, lodashSubpathPlugin, dropEthersWordlistsPlugin,
|
|
226
243
|
],
|
|
227
244
|
external: ["cloudflare:*", "__STATIC_CONTENT_MANIFEST"],
|
|
228
245
|
// Give import.meta.url a stable fallback so bundled deps that call
|
|
@@ -265,6 +282,10 @@ build({
|
|
|
265
282
|
// axios → lightweight fetch-based shim (115KB → ~2KB)
|
|
266
283
|
"axios": s("shims/axios-lite.ts"),
|
|
267
284
|
|
|
285
|
+
// node-fetch → native fetch (drops encoding/tr46/whatwg-url polyfill ~754KB
|
|
286
|
+
// pulled in by @apple/app-store-server-library; dead weight on CF Workers)
|
|
287
|
+
"node-fetch": s("shims/node-fetch.ts"),
|
|
288
|
+
|
|
268
289
|
// Stripe — wrap constructor to use fetch HTTP client in CF Workers
|
|
269
290
|
"stripe": s("shims/stripe-cf.ts"),
|
|
270
291
|
"__real_stripe__": require.resolve("stripe"),
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// node-fetch shim for CF Workers — forwards to the runtime's native fetch.
|
|
2
|
+
// node-fetch is pulled in transitively by @apple/app-store-server-library (IAP
|
|
3
|
+
// JWS verification). On Node it drags in a polyfill chain that is dead weight on
|
|
4
|
+
// Workers (which has native fetch/URL/TextDecoder):
|
|
5
|
+
// encoding (iconv-lite CJK code tables) 481KB + tr46 (IDNA map) 259KB
|
|
6
|
+
// + whatwg-url 22KB + node-fetch 19KB ≈ 781KB, never executed at runtime.
|
|
7
|
+
// Forwarding node-fetch → native fetch drops that whole chain (~754KB raw).
|
|
8
|
+
// Only implements the node-fetch v2 export surface actually referenced.
|
|
9
|
+
|
|
10
|
+
export default globalThis.fetch.bind(globalThis);
|
|
11
|
+
|
|
12
|
+
export const Headers = globalThis.Headers;
|
|
13
|
+
export const Request = globalThis.Request;
|
|
14
|
+
export const Response = globalThis.Response;
|
|
15
|
+
export const FormData = globalThis.FormData;
|
|
16
|
+
export const Blob = globalThis.Blob;
|
|
17
|
+
|
|
18
|
+
export class FetchError extends Error {
|
|
19
|
+
type: string;
|
|
20
|
+
constructor(message: string, type = 'system') {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'FetchError';
|
|
23
|
+
this.type = type;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class AbortError extends Error {
|
|
28
|
+
type = 'aborted';
|
|
29
|
+
constructor(message: string) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = 'AbortError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const isRedirect = (code: number) => [301, 302, 303, 307, 308].includes(code);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.1",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "blocklet dev --open",
|
|
6
6
|
"prelint": "npm run types",
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
"@blocklet/error": "^0.3.5",
|
|
63
63
|
"@blocklet/js-sdk": "^1.17.12",
|
|
64
64
|
"@blocklet/logger": "^1.17.12",
|
|
65
|
-
"@blocklet/payment-broker-client": "1.29.
|
|
66
|
-
"@blocklet/payment-react": "1.29.
|
|
67
|
-
"@blocklet/payment-vendor": "1.29.
|
|
65
|
+
"@blocklet/payment-broker-client": "1.29.1",
|
|
66
|
+
"@blocklet/payment-react": "1.29.1",
|
|
67
|
+
"@blocklet/payment-vendor": "1.29.1",
|
|
68
68
|
"@blocklet/sdk": "^1.17.12",
|
|
69
69
|
"@blocklet/ui-react": "^3.5.2",
|
|
70
70
|
"@blocklet/uploader": "^0.3.20",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"devDependencies": {
|
|
141
141
|
"@abtnode/types": "^1.17.12",
|
|
142
142
|
"@arcblock/eslint-config-ts": "^0.3.3",
|
|
143
|
-
"@blocklet/payment-types": "1.29.
|
|
143
|
+
"@blocklet/payment-types": "1.29.1",
|
|
144
144
|
"@types/cookie-parser": "^1.4.9",
|
|
145
145
|
"@types/cors": "^2.8.19",
|
|
146
146
|
"@types/debug": "^4.1.12",
|
|
@@ -188,5 +188,5 @@
|
|
|
188
188
|
"parser": "typescript"
|
|
189
189
|
}
|
|
190
190
|
},
|
|
191
|
-
"gitHead": "
|
|
191
|
+
"gitHead": "e66e469df2a1ed80e15b17fd8511c2ce01a0a54e"
|
|
192
192
|
}
|