本文用微信小程序 + 云开发,从零搭建一套面向高原弱网的优化能力,覆盖本地缓存、请求重试、图片懒加载、离线队列的完整实现。基于青海青帝科技技术团队的本地项目实践整理。
在云开发小程序上实现:
- 首屏在弱网下 3 秒内可交互;- 图片使用 WebP、按需缩放、懒加载;- 请求带超时重试、失败读缓存;- 关键操作支持离线记录、恢复后同步。
弱网优化的基础是一个可靠的请求封装。云开发的小程序端通过 wx.cloud.callFunction 调云函数,我们把它封装成带超时、重试、缓存的能力:
// utils/request.js —— 云函数调用封装:超时 + 重试 + 缓存
const CACHE_PREFIX = 'cache_';
async function callWithRetry(name, data, options = {}) {
const { timeout = 10000, retries = 2, cacheKey } = options;
let lastErr;
for (let i = 0; i <= retries; i++) {
try {
const res = await Promise.race([
wx.cloud.callFunction({ name, data }),
new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), timeout)),
]);
if (cacheKey) wx.setStorageSync(CACHE_PREFIX + cacheKey, res.result);
return res.result;
} catch (e) {
lastErr = e;
}
}
// 全部失败,兜底读缓存
if (cacheKey) {
const cached = wx.getStorageSync(CACHE_PREFIX + cacheKey);
if (cached) return cached;
}
throw lastErr;
}
module.exports = { callWithRetry };要点:Promise.race 实现超时,循环实现重试,失败后兜底读缓存,保证弱网下"有内容可看"。
这里解释一下为什么要把这三个能力(超时、重试、缓存)封装在一起,而不是分开写:弱网下它们往往是"组合生效"的——请求先超时,然后重试,重试仍失败才读缓存。如果分开写,业务代码里就会散落一堆 try/catch 和重试逻辑,难以维护。封装成一个统一的 callWithRetry,业务代码只需关心"拿数据"这一件事,弱网的处理全部收敛到一处。这是弱网适配里很重要的一条工程原则:把弱网的复杂性封装在基础设施层,别让它污染业务代码。
关于超时时间的设置,也有讲究:超时太短,弱网下正常请求也会被误杀;超时太长,用户等太久。一般取 8—10 秒比较稳妥,配合 2 次重试,最坏情况下用户等待约 30 秒,此时已经兜底读了缓存,界面不至于空白。这个值不是拍脑袋定的,是结合弱网实测和用户耐心阈值权衡出来的。
图片是弱网优化的头号目标。用 WebP、按需缩放、懒加载三管齐下。
// utils/image.js —— 图片地址处理:转 WebP + 按需缩放
function smartUrl(url, width) {
// 转 WebP(腾讯云 COS 数据处理示意,具体参数以 COS 为准)
let u = url + (url.includes('?') ? '&' : '?');
u += `imageMogr2/format/webp`;
if (width) u += `/thumbnail/${width}x`;
return u;
}
懒加载用 IntersectionObserver:
// 列表页懒加载
const observer = wx.createIntersectionObserver(this);
observer.relativeToViewport({ bottom: 200 })
.observe('.lazy', (res) => {
if (res.intersectionRatio > 0) {
const { id } = res.dataset;
this.setData({ [`loadedMap.${id}`]: true });
}
});图片这三板斧(WebP、按需缩放、懒加载)组合起来的收益是很可观的:一张列表页如果有 20 张图,每张从 2MB 降到 100KB(WebP + 缩放到 750 宽),整体流量能从 40MB 降到 2MB,减少 95%。这在弱网下,就是"等 1 秒"和"等 1 分钟"的差别。图片优化是弱网优化里性价比最高的一项,建议优先做、做彻底。
另外要提醒:懒加载虽然省流量,但如果预加载距离(bottom: 200)设得太小,用户快速滑动时图片会来不及加载,反而出现"滑到哪空白到哪"的体验。bottom 参数要留够余量,一般 200—300 比较合适,具体结合图片大小和弱网速度实测调整。
对牧区、山区长时间断网的场景,关键操作要先写本地队列,恢复后同步。云开发的云函数天然适合做同步端点:
// utils/offline.js —— 离线队列
const QUEUE_KEY = 'offline_queue';
function enqueue(action) {
const queue = wx.getStorageSync(QUEUE_KEY) || [];
queue.push({ ...action, ts: Date.now() });
wx.setStorageSync(QUEUE_KEY, queue);
}
async function flush() {
const queue = wx.getStorageSync(QUEUE_KEY) || [];
if (!queue.length) return;
const { callWithRetry } = require('./request');
const failed = [];
for (const action of queue) {
try {
await callWithRetry('syncAction', action, { retries: 1 });
} catch (e) {
failed.push(action);
}
}
wx.setStorageSync(QUEUE_KEY, failed); // 仅保留失败项
}
// 监听网络恢复
wx.onNetworkStatusChange((res) => {
if (res.isConnected) flush();
});要点:同步失败的项保留在队列里,下次网络恢复再同步,避免数据丢失。
弱网优化不只是客户端的事,云函数侧也要做减法。
1. 字段裁剪。 列表云函数只返回列表需要的字段,详情字段延迟到详情云函数再取:
// cloudfunctions/getList/index.js —— 列表只返回必要字段
const cloud = require('wx-server-sdk');
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
const db = cloud.database();
exports.main = async (event) => {
const { page = 1, size = 20 } = event;
const res = await db.collection('article')
.field({ _id: true, title: true, cover: true, summary: true })
.skip((page - 1) * size)
.limit(size)
.get();
return res.data;
};2. 分页。 长列表强制分页,避免一次性返回大量数据。
3. 幂等。 写操作(如提交订单)带幂等键,配合客户端重试,避免重复写入:
// cloudfunctions/createOrder/index.js —— 幂等处理
exports.main = async (event) => {
const { idempotency_key, ...order } = event;
const exist = await db.collection('order')
.where({ idempotency_key }).count();
if (exist.total > 0) return { code: 0, msg: 'duplicated' };
await db.collection('order').add({ data: { ...order, idempotency_key } });
return { code: 1, msg: 'ok' };
};幂等是弱网下"重试"能安全进行的基石。没有幂等,客户端重试就可能重复下单、重复提交,这在弱网场景下几乎必然发生——因为弱网下"请求其实成功了、但响应超时丢失"的情况非常常见,客户端无法区分"没发出去"和"发出去了没收到回执",只能重试。有了幂等键,服务端能识别重复请求并去重,重试才安全。可以说,幂等设计是弱网容错里最容易忽略、却最关键的一环。
对热点数据(首页框架、配置),云函数侧可配合缓存,客户端配合条件请求减少重复传输。云开发的数据库查询本身有缓存,进一步可在云函数内用内存缓存热点数据,减少数据库压力。
上线前逐项自检:
1. 弱网模拟下首屏是否 3 秒内可交互;2. 图片是否 WebP、按需缩放、懒加载;3. 请求是否有超时、重试、失败读缓存;4. 关键操作是否离线记录、恢复同步、幂等;5. 列表是否字段裁剪、分页;6. 是否在真实弱网环境测试过。
高原弱网的优化,客户端和云函数要配合着做:客户端做"资源瘦身、缓存、重试、离线队列",云函数做"字段裁剪、分页、幂等、缓存"。用云开发可以快速搭起这套能力,让应用在弱网甚至断网下仍能稳定运行。对青海本地的团队而言,弱网适配不是一次性优化,而是可以长期复用的工程能力,越早沉淀,越能在面向牧区、山区的项目中占据主动。
公司技术团队在本地项目中沿用这套流程,把弱网适配沉淀为可复用的工程底座,显著提升了应用在高原弱网环境下的可用性。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。