← 返回日记列表科技学习日记

一个非工程师,三周从零做出微信小程序:跨端架构与合规妥协

10 分钟阅读
投资大师之路最初只是一个 H5 网站——用浏览器打开就能玩。但当我想把它推到"日活更高的入口"时,所有路径都指向了**微信小程序**。中国互联网你可以不用任何 App,但很难不用微信。 但小程序不是"H5 套壳"。这一篇是我作为非工程师,三周内把这个项目从 H5 重写到原生微信小程序的完整记录——包括踩到的合规雷、跨端共享数据的架构、以及个人主体的现实约束。 ### Step 0:H5 套壳为什么走不通 最朴素的想法是:在小程序里放一个 `<web-view>` 组件加载 master-ai.cn/gam3,一行代码搞定。 走不通。微信对 `<web-view>` 有三层硬限制: 1. **个人主体小程序禁用 `<web-view>`**——这是硬规则,没有任何绕过空间。 2. 业务域名(webview-domain)需要企业认证 + 行业资质,个人申请不下来。 3. 即使企业主体能用,微信运营规范明确禁止"纯 webview 套壳"——审核员发现整个小程序就是一个 webview 加载外部网页,会直接驳回。 > **微信生态对原生小程序的偏好不是建议,是政策**。Skyline 渲染引擎、订阅消息、自定义分享卡、支付能力——这些只对原生开放。webview 永远是二等公民。 所以唯一的路径是:**用小程序原生技术栈(WXML/WXSS/Page)重写整个前端**。 ### Step 1:评估真实工作量 我先逐文件统计了 H5 版本的代码体量: - `runner-v4.js`:2035 行,69 个函数。覆盖剧本状态机、HUD、对话/选项/头条/信息卡/锦囊/交易确认弹窗、Ken Burns 背景、Mini K 线 + 全屏 K 线、章末复盘、净值曲线、html2canvas 分享图。 - `style-v4.css`:1200 行,电影感视觉风格。 - 60 个章节背景图,14 个人物立绘,60+ JSON 文件。 让 LLM 一次性翻译成 WXML/WXSS/Page 是不现实的——细节差异太多。我必须**逐层重写**,并且**砍掉一部分功能换合规性**。 ### Step 2:合规边界(可能比技术更重要) 个人主体小程序选了"工具/查询"类目。审核员看一眼小程序里如果有任何"投资建议"嫌疑,就会拒。我把 H5 版的功能矩阵划成两类: **砍掉**(v1 不上): - 模拟交易(买/卖按钮、股数输入、盈亏 HUD) - K 线图(看起来太像股票软件) - 自由交易窗口 + 自动播放 - 期货章节("棉花""螺纹钢"——期货关键词敏感) - 任何"建议买入/卖出"措辞 **保留**: - 剧情对话、选项、头条卡、信息卡 - "大师当时怎么想"——把原来的"💡 大师锦囊"改名,去掉"建议"语义 - 章末复盘(纯文字,不画净值曲线) 定位从"投资互动游戏"调整成"投资史互动阅读器"。**功能砍掉一半,但过审概率从 30% 拉到 95%**。 ### Step 3:跨端数据架构(这一步最关键) 最大的工程问题:**怎么让 H5 版和小程序版共用一份内容?** 如果数据打进小程序包,每次加新章节都要重新提交审核(小程序代码版本审核通常 1-3 天)。这显然不可接受——内容产品的核心是"快速迭代剧本"。 最终落地的架构: ``` master-ai.cn/gam3/ ← 静态托管 (HTTPS + ICP 备案) ├── chapters.json ← 章节列表 ├── script-*.json ← 各章节剧本 ├── prices-*.json ← 历史价格 (合规版不读) ├── headlines-*.json ← 头条卡 ├── advices-*.json ← 大师当时怎么想 ├── infoCards-*.json ← 信息卡 └── art/ ← 背景 + 人物插画 ``` H5 版直接 fetch,小程序版用 `wx.request` 拉。
文章配图
小程序端的 `utils/api.js` 实现了一个简单的 cache-first 策略: ```js function fetchJson(path, onUpdate) { // 1. 缓存有就立即回调一次(用户立即看到内容) const cached = readCache(path); if (cached) onUpdate(cached.data, true); // 2. 同时后台请求最新版(用户网络好就秒级更新) wx.request({ url: `${BASE_URL}/${path}`, success: (res) => { writeCache(path, res.data); onUpdate(res.data, false); } }); } ``` **红利**:以后我改剧本只需要把 JSON push 到 master-ai.cn——H5 版立即生效,小程序版下次启动自动拉到(用户感知是"无缝更新")。**小程序代码本身不需要重新审核**。 这个架构在我反复阅读微信文档后才确认是合规的——只要 `wx.request` 拉的内容本身合规、域名是 ICP 备案的 HTTPS 域名,就没问题。 ### Step 4:状态机改造 H5 版的 `runner-v4.js` 是 DOM 操作风格——直接 `document.getElementById`、`innerHTML`、`addEventListener`。小程序是数据驱动 + `setData`,必须改造。 我把核心 2000 行剧本引擎重写成一个**纯函数式状态机**: ```js class ChapterRunner { start() { this._step(); } advance() { /* 推进对话/卡片 */ } choose(idx) { /* 选了第 idx 个选项 */ } _step() { // 不断 _executeNode 直到遇到 wait(对话/选项/卡片) // 触发 onStateChange 回调 // Page 收到回调用 setData 渲染 } } ``` 精髓是:**runner 不知道 WXML 长啥样,Page 不知道剧本逻辑长啥样**。两者通过 onStateChange 一个回调通信。这套架构 H5 版照样能用——本质上是个跨端的状态机。 代码体量从原来 2035 行的 `runner-v4.js` 缩到 280 行的小程序版(因为砍掉了 K 线、交易、复盘画图等模块)。 ### Step 5:剩下的小坑 - **图片 URL**:小程序的 `<image>` 组件可以直接用 https URL,但要在小程序后台"服务器域名"里加 `master-ai.cn` 进 `request 合法域名` 列表。开发版可以勾"不校验合法域名"先调试。 - **textarea 焦点**:小程序的 textarea 在 iOS 上键盘弹起会顶住整个布局,要用 `fixed` + `adjust-position` 处理。 - **wx.setStorageSync 单 key 1MB 上限**:我在 cache 层做了分桶,每个 JSON 文件单独存一个 key。 ### 总成本盘点 - 实际投入:每天 2-3 小时 × 18 天 ≈ 50 小时 - 工具:Claude Code 全程协作,几乎每个文件第一版都是它写的,我做架构决策和合规裁剪 - 砍掉的功能:交易模拟、K 线、复盘画图、分享图——大约 40% 的 H5 版功能 - 没砍掉的红利:跨端数据架构(最重要的工程沉淀) > 做完后我才理解微信生态"原生优先"政策的深意。如果走 webview 套壳,三个月后我还在原地打转——加一个新功能就要重新备案、重新审核、还要应付各种限流。**而走原生 + 数据云端架构,我每天都能上一篇新章节,平台甚至会因为我"内容更新活跃"给更多曝光**。 最后一个意外发现:把这一整套架构迁移过程当作一个产品案例写出来,本身就是一个挺好的内容产品。所以才有了这一篇文章。