小程序登录、支付与订阅消息实战
wx.login 会话、code2Session、支付签名、订阅消息模板与前后端协作的安全边界。
双线程模型、setData 优化、分包策略、Skyline 渲染与 Taro 跨端选型的系统化指南。
电商小程序商品列表页,首屏 80 SKU + 多 tab 筛选,旧版每次筛选 setData 整表 120KB+,Android 低端机 scroll 掉帧到 25fps。改用 自定义组件隔离 + 路径更新 + 虚拟列表 后,单次 setData payload 降到 8KB 以内,滚动稳定 55fps+。
逻辑层(JSCore)与渲染层(WebView)通过 Native 序列化通信。setData 不是赋值,是 IPC。
用户 tap
→ View 层捕获事件
→ Native 转发
→ AppService 逻辑层 handler
→ setData(diff) 序列化
→ Native → View patch DOM
推论:减少 setData 次数、减小 payload、缩小 diff 范围,比「换更快算法」有效。
// ❌ 整表替换 — 我们测过 ~120KB/次
this.setData({ list: newList, loading: false });
// ✅ 路径更新
this.setData({
'list[2].stock': 0,
loading: false,
});
// ✅ 子组件内 setData — 只 patch 子树
Component({
methods: {
updatePrice(price) {
this.setData({ price }); // 仅本组件
},
},
});
| 手段 | 我们收益 |
|---|---|
| 路径更新 | payload -70% |
| 子组件隔离 | diff 范围 -80% |
合并 setData(wx.nextTick 批处理) | 连续操作 5 次 → 1 次 |
recycle-view / 虚拟列表 | 长列表必做,DOM 节点 < 20 |
微信开发者工具 → Audits / Trace,看 setData 耗时与数据大小。我们规定:单次 setData serialized < 64KB,超了必须拆组件。
Skyline 用 原生渲染路径 替代部分 WebView 布局,滚动与动画更顺。启用:
{
"renderer": "skyline",
"componentFramework": "glass-easel",
"lazyCodeLoading": "requiredComponents"
}
| 对比 | WebView | Skyline |
|---|---|---|
| 长列表 scroll | 易 jank | 明显改善 |
| 自定义组件 | 全支持 | 需查兼容表 |
| 包体积 | 无额外 | 略增 |
我们 活动页先 Skyline 试点,主购物流仍 WebView——迁移要逐页测 wxss 与第三方组件。
{
"pages": ["pages/home/index"],
"subPackages": [
{ "root": "pkg-order", "pages": ["list/index", "detail/index"] },
{ "root": "pkg-user", "pages": ["profile/index"] }
],
"preloadRule": {
"pages/home/index": { "network": "wifi", "packages": ["pkg-order"] }
}
}
主包 < 1.5MB(留审核余量);按 访问频率 拆 pkg,不是按团队组织架构。
// 支付仅小程序
{process.env.TARO_ENV === 'weapp' && (
<Button onClick={handleWechatPay}>微信支付</Button>
)}
我们选 Taro 因为团队 React 栈统一;复杂动画页仍原生小程序——编译抽象有成本,ROI 要算。
wx.onError / wx.onUnhandledRejection → 统一 SDK(见 埋点 SDK)scene、机型进上下文wx.login → code → 后端换 session
wx.requestPayment → 商户号配置 + 签名校验在后端
订阅消息 → 用户授权模板 id → 服务端下发
前端 不存 session secret;支付结果以服务端回调为准,前端仅展示轮询状态。
小程序性能 = 理解双线程 + 测量 setData + 分包 Skyline 渐进。没有 trace 数据的优化都是猜。