微信小程序云开发:从反复踩坑到第一性原理

半路笔记 · 技术实践


我花了整整一天,在一个小程序上踩了大概 15 个坑,最终靠一个问题的解决才全部炸开。这篇文章不讲”方法论”,只讲我踩的坑、踩完之后明白的事,以及为什么”从第一性原理出发”这句话不是口嗨。

背景

小程序叫「半路笔记」,功能很简单——首页展示文章列表,点击进入详情。数据存在微信云开发的云数据库里,通过云函数读取。技术栈是微信原生开发 + 云函数(Node.js)。

就这么简单的事,Debug 花了一天。

第一个坑:云开发入口在哪

微信开发者工具(macOS Stable 2.01.2510290 版本)的菜单里,没有一个叫「云开发」的选项。我花了快一个小时,在公众号后台、小程序后台、腾讯云控制台之间反复横跳。

最终发现:入口是工具栏上「真机调试」按钮右边一个极不起眼的小图标。不是菜单项,不是右键菜单,不是设置页。是工具栏上一个连标签都没有的小图标。

这一个坑教会我一个道理:微信的开发体系有两套管理面——腾讯云 CloudBase(管理资源)+ 微信云开发控制台(管理小程序绑定)。它们是两套独立系统,互相看不到对方的环境。

第二个坑:环境ID的平行宇宙

我在腾讯云创建了一个环境 banlu-notes,然后把环境ID填进了 app.js。满心以为搞定了。

不行。报 -601034:没有权限。

原因是:小程序 SDK 需要的不是腾讯云的 CloudBase 环境,而是微信侧的云开发环境。两者虽然底层可能是同一套基础设施,但 AppID 绑定只发生在微信侧。

我重新在微信云开发控制台创建了环境 cloud1,环境ID cloud1-xxxxxxxxxxxxxxxx。现在有两个环境并存:腾讯云的 banlu-notes(死路,小程序 SDK 不能用)和微信云的 cloud1(正确,AppID 绑定的)。

这是第二个教训:环境有两套,别填错了。

第三个坑:SDK 的 mock 地狱

环境搞定、数据导入、云函数部署,一切就绪。编译。

报:Env Not Exists (...随机UUID...)

我换了环境ID。报。再换。报。显式传入 env 参数。报。在调用的时候传入 config.env。报。延迟初始化。报。

每次报的环境 ID 都不一样——有时是 316364d9-865a...,有时是 bb35365b-358b...,有时是 82c03dc7-ce5c...。全部是随机生成的假 UUID。

这意味着 SDK 完全没有读我的环境配置。它自己生成了一套 mock 环境,然后把所有请求都路由到这个不存在的假环境上。

我换了四个运行模式测试:

  • 模拟器 → mock
  • 真机调试 → mock
  • 真机预览 → mock
  • 清除缓存重新打开 → 还是 mock

改了 6 轮代码,全部无效。

破局:第一性原理

到晚上 8 点多,我对自己说了一句话:“从第一性原理出发再考虑一下。”

我开始问自己最基础的问题:

“SDK 为什么要生成 mock 环境?”

不是”报错信息是什么”,不是”哪个参数没传对”,而是”什么机制导致了这个行为”。

答案:SDK 在初始化时检查项目是否是云开发项目。如果不是,就进入 mock 模式。而且——这个检查发生在 wx.cloud.init() 之前,所以代码里怎么传 env 都没用。

那么下一个问题:SDK 怎么判断项目是不是云开发项目?

它读 project.config.json。我的文件里写着 "cloud": true。为什么它还判断为非云开发?

继续追问:是 cloud: true 没生效,还是被什么字段覆盖了?

我打开 project.config.json 仔细看。这个文件是在新建项目时,从一个叫 quickstart-wx-cloud 的模板复制过来的。它里面有一个字段:

"cloudfunctionTemplateRoot": "cloudfunctionTemplate/"

这个字段是旧版模板特有的,在新版 SDK 里已经被废弃了。但它留在 json 里,很可能干扰了 SDK 的初始解析——SDK 优先匹配到了旧模板的结构,然后跳过了新版 cloudBaseEnvId 的读取路径。

还有两个残留:

  • projectname: "quickstart-wx-cloud"——旧模板名
  • libVersion: "2.20.1"——与 project.private.config.json 里的 3.16.2 冲突

这三个字段就像一个旧锁芯卡在新锁里。你能把钥匙(环境ID)插进去,但打不开。

修复

删除 project.config.json 中的所有旧模板残留字段,重写为:

{
  "miniprogramRoot": "miniprogram/",
  "cloudfunctionRoot": "cloudfunctions/",
  "cloud": true,
  "cloudbaseRoot": "cloudfunctions/",
  "cloudBaseEnvId": "your-env-id-here",
  "compileType": "miniprogram",
  "libVersion": "3.16.2",
  "appid": "your-appid-here",
  "projectname": "banlu-miniprogram"
}

同时简化 project.private.config.json,不再在里面放云开发配置(避免覆盖冲突)。

app.js 和 index.js 也不强行传 env 参数,让 cloudBaseEnvId 自动生效。

好了

重开开发者工具,编译。

[APP] wx.cloud.init 完成(使用 cloudBaseEnvId 默认环境)
[DEBUG] 云函数返回 code= 0
[DEBUG] 取得 1 条文章

模拟器里出现了文章。

第一性原理不是口嗨

这次 Debug 的前 15 次试错,每次都在修同一个层级的变量——环境ID。换一个,不对,再换一个。

第一性原理做的是向下穿透一层:不修”参数值”,修”参数被谁读、怎么读”。

对比一下两种思维路径:

试错法:                                                    第一性原理:
报错 → 环境ID错了 → 换个ID → 还报错 → 再换 → 死循环         报错 → SDK 为什么生成 mock?→ 它怎么判断环境?

                                                             → 读 project.config.json

                                                             → 为什么有 cloud:true 还不读?

                                                             → 旧模板残留字段干扰了解析

                                                             → 删除残留 → 解决

一句话:试了 3 次还没解决的,停。问”这个系统的读取机制是什么”,而不是”这个值对不对”。

后续

文章在云数据库里,不在代码里。每次新增文章不需要重新审核——导入数据即可,小程序实时更新。

审核中,等上线。


写于 2026-07-08 北京·半路技术记录