部署工具?别扯了,先活下来再说
做了6年iOS开发的老兵,在Swift从1.0一路肝到5.9的路上,没少被Xcode和CI/CD折磨。现在刚入职新公司两个月,每天一边用ChatGPT写代码,一边怀念以前能摸鱼的日子。
去年双11前一周,我们团队临时接到一个需求:老板说想把公司那本《区块链赋能下一代数字阅读》的电子书上链——对,你没看错,就是那种听起来很玄乎但其实谁也说不清怎么“赋能”的项目。产品经理画了一张PPT,说要打造“去中心化数字书籍分发平台”,还找了几个投资人站台。
我当时就懵了。作为一个纯客户端出身的iOS工程师,我连以太坊钱包都没正经用过,结果现在要搞部署?而且deadline就在下周三上线发布会!
更离谱的是,运维大哥上周刚提了离职,交接文档只有一行字:“部署脚本在Jenkins里,自己看。” 我点进去一看,Jenkinsfile全是Groovy写的,变量名还是拼音缩写……那一刻我真的想砸MacBook。
从“Hello World”到“Hello Production”
说实话,我之前对部署的理解仅限于Archive → Export → 上传App Store Connect。顶多加个Fastlane自动签名。但现在,后端服务、智能合约、链上交互、静态资源托管……全堆在我头上。毕竟新公司人少,一人多岗是常态,我这个“资深iOS”被迫成了“全栈临时工”。
好在有Claude和ChatGPT救我狗命。我直接甩给它一句:“帮我写一个能部署Solidity合约 + 静态网页 + API网关的自动化脚本,支持测试网和主网切换。” 它还真吐出来一套方案,虽然第一次跑直接报错:
Error: insufficient funds for gas * price + value
我:???我钱包里只有0.002 ETH,测试网领水都领不到(Rinkeby已停,Goerli也快没了)。还好同事借了我点Sepolia测试币,不然发布会当天怕是要现场表演“区块链未连接”。
工具选型:稳字当头,别整花活
虽然我喜欢折腾新技术(比如最近在研究Swift Concurrency和VisionOS),但工作项目?能用老办法就绝不碰新轮子。毕竟线上崩了,背锅的还是我。
所以这次部署方案,核心原则就一条:简单、可回滚、日志清晰。
后端API:Vercel + Serverless Functions
原本想用AWS Lambda,但配置IAM角色差点让我原地升天。最后选了Vercel——不是因为它多牛,而是因为它的部署命令就一行:
vercel --prod
而且它自带环境变量管理、预览分支、回滚功能。最关键的是,前端同事也能看懂,不用每次改个API都要我手把手教。
智能合约:Hardhat + Ethers.js
Solidity生态里,Truffle已经有点老了,Foundry又太新(文档少得可怜)。Hardhat社区活跃,插件多,还能本地fork主网调试——这对模拟“书籍上链”这种操作太重要了。比如我想测试一本书的元数据是否正确写入IPFS并关联到NFT,直接:
await network.provider.request({
method: "hardhat_impersonateAccount",
params: ["0x真实作者地址"],
});
瞬间变身作者,调用他的合约函数,爽到飞起。
静态页面 & 书籍展示:IPFS + Cloudflare
书的内容不能放中心化服务器,否则还叫什么“去中心化”?所以我们把PDF转成加密哈希,存到IPFS。但IPFS网关慢得像蜗牛,用户打开要等10秒……
解决办法:Cloudflare 的 IPFS 网关加速。配置完之后,访问 https://cloudflare-ipfs.com/ipfs/<CID> 快如闪电。而且Cloudflare Pages还能自动部署前端,配合GitHub Actions,代码一推,页面就更新。
踩坑实录:那些让我凌晨三点还在debug的瞬间
坑1:环境变量泄露到Git
我一开始图省事,把Infura的API Key直接写进.env,然后git add .……还好被GitGuardian的PR检查拦住了。不然发布会一开,我的Infura额度被机器人刷爆,账单够买台Mac Studio。
教训:所有敏感信息必须通过部署平台的环境变量注入,本地用.env.example模板。
坑2:合约升级?别想了
老板中途突然说:“能不能让用户修改书名?” 我内心一万只羊驼奔腾——NFT元数据一旦上链,基本不可变!除非用ERC-721的可升级代理模式,但那复杂度直接翻倍。
最后妥协方案:在链下数据库存一个“显示名称”,链上只存原始哈希。等于打了个补丁,但至少能交差。
坑3:iOS WebView加载IPFS内容白屏
最离谱的是,我在App里用WKWebView加载IPFS链接,结果在真机上一片白!调试半天发现,iOS默认禁止加载非HTTPS内容,而很多IPFS网关是HTTP的。
解决方案:强制用Cloudflare的HTTPS网关,并在Info.plist里加:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>cloudflare-ipfs.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
但说实话,这属于安全例外,上线前被安全团队骂了半小时。
自动化部署流水线:从手动到“一键起飞”
刚开始,部署流程是这样的:
- 手动编译合约
- 复制ABI到前端
- 手动上传PDF到IPFS
- 复制CID到合约参数
- 手动部署前端到Vercel
- 手动更新iOS App的配置文件
我干了两次就崩溃了。于是花了周末两天,搞了个CI/CD流水线。
GitHub Actions 脚本长这样:
name: Deploy Book Platform
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install deps
run: npm install
# 1. 部署合约(仅当合约代码变更时)
- name: Deploy Contract
if: github.event.head_commit.message == 'deploy contract'
run: npx hardhat run scripts/deploy.js --network sepolia
env:
INFURA_KEY: ${{ secrets.INFURA_KEY }}
DEPLOYER_PRIVATE_KEY: ${{ secrets.DEPLOYER_PK }}
# 2. 上传书籍到IPFS
- name: Upload Book to IPFS
id: ipfs
run: |
CID=$(npx pinata-upload ./books/latest.pdf)
echo "book_cid=$CID" >> $GITHUB_OUTPUT
env:
PINATA_API_KEY: ${{ secrets.PINATA_API_KEY }}
PINATA_SECRET_KEY: ${{ secrets.PINATA_SECRET_KEY }}
# 3. 构建前端并注入CID
- name: Build Frontend
run: |
echo "REACT_APP_BOOK_CID=${{ steps.ipfs.outputs.book_cid }}" > .env
npm run build
# 4. 部署到Vercel
- name: Deploy to Vercel
run: npx vercel --prod --token ${{ secrets.VERCEL_TOKEN }}
现在,只要产品经理把新书PDF放进/books目录,推到main分支,整个平台自动更新。我甚至可以在Slack里收到通知:“《如何用区块链卖书》已上链,CID: Qm...”。
效果与反思:值不值得?
发布会当天,系统居然没崩!用户扫码就能看到自己的“数字藏书”,还能在App里查看链上记录。虽然日活只有200人(大部分是内部员工),但老板很满意,说这是“技术驱动业务创新”。
但冷静下来想想,这套部署方案真的适合所有项目吗?
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Vercel + Hardhat + IPFS | 快速、低成本、去中心化 | 调试复杂、依赖第三方网关 | MVP、概念验证、小众DApp |
| AWS + Kubernetes + 自建IPFS节点 | 可控性强、性能高 | 运维成本极高、学习曲线陡 | 高并发、企业级应用 |
| Firebase + 中心化存储 | 简单、集成快 | 不符合“去中心化”理念 | 传统App,无需上链 |
对我们这种小团队来说,第一种刚刚好。但如果真要做大规模数字书籍平台,可能还得回归中心化+链上存证的混合架构。
给 fellow iOS 开发者的建议
如果你和我一样,是个客户端出身却被逼搞部署的倒霉蛋,记住几点:
- 别试图一个人搞定所有:找后端同事结对编程,哪怕他只会写Java。
- 善用AI,但别全信:ChatGPT生成的脚本一定要逐行检查,特别是涉及钱(gas费)的操作。
- 先跑通,再优化:MVP阶段别纠结架构,能跑就行。等产品验证了再重构。
- 日志!日志!日志!:部署失败时,没有日志等于盲人摸象。
最后说点人话
写这篇文章的时候,我刚处理完一个线上Bug:用户反馈“书不见了”。查了半天,发现是因为IPFS的Pinata服务免费额度用完了,文件被自动unpin……现在我们已经改成付费套餐+多节点备份。
你看,所谓的“去中心化”,最后还是得靠中心化的服务商兜底。这世界哪有什么真正的去中心化,不过是把信任从银行转移到Infura和Pinata罢了。
不过话说回来,折腾这些虽然累,但确实让我从“只会写UI的iOS仔”变成了能端到端交付的工程师。下次跳槽,简历上终于可以写“主导区块链数字内容平台部署架构”了(笑)。
对了,那本书现在还在链上,CID是 QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco。感兴趣的朋友可以去IPFS看看——虽然内容大概率是“区块链将颠覆出版业”之类的陈词滥调。
但至少,它真的上链了。而我,也真的活下来了。
PS:如果你也在用Hardhat + Vercel搞DApp,欢迎交流。不过别问我怎么省钱,我现在每个月光Infura和Pinata账单就快赶上房租了……

评论 0