☰
小程序后台要不要做?六道判断题与平滑演进架构
2026/10/30 6:06:56 网站建设 项目流程

先给你一个真实场景:上周有个做自媒体的朋友拿了个半成品小程序来找我,说功能都跑通了,就是不知道要不要再花钱买台服务器。我打开代码一看,数据全放在本地缓存里,页面里还硬编码了一个第三方接口的密钥。这个问题表面上是“要不要后台”,实际上是个选型判断加架构预留的活儿——答“要”或“不要”都太草率。这篇就把小程序后台这件事从头拆开:后台到底在替你承担哪些职责、什么条件下可以彻底不要、什么条件下省掉的成本会以另一种方式还回来、以及即便现在不接后台,代码该怎么写才能在三周后平滑接上。不管你是刚跑通第一个 Demo 的新手,还是正在给团队做技术选型的负责人,都能从里面拿到可直接用的判断清单和代码骨架。

1. “必须要有后台吗”这句话,实际上混着三个不同的问题

大部分人问出这句话的时候,脑子里想的其实是三件事缠在一起:我的数据放哪儿、我的密钥藏哪儿、我以后改东西要不要重新提审。这三个问题的答案完全不同,混在一起问就永远得不到答案。所以先做一次拆解,把“后台”这个词从抽象概念还原成具体职责,后面的判断才有落脚点。

1.1 后台在替你干的五件事,没有一件是“因为大家都这么做”

我把这些年接触过的小程序后台归了归类,无论技术栈怎么换,它承担的职责就这五类。第一类是跨用户、跨设备的数据持久化,比如订单、聊天记录、用户资产,这类数据的特点是“换台手机必须还在”,只要沾上这条,纯本地方案基本出局。第二类是可信身份与权限判定,客户端能改的东西都不能当证据,谁是会员、这单能不能退,必须由一段用户碰不到的代码来裁决。第三类是密钥托管与第三方调用中转,任何写进前端包里的密钥都等于公开的密钥,抓个包就看见了。第四类是时间维度上的任务,定时清理、延迟推送、批量对账,客户端根本没机会在用户关掉小程序之后继续跑。第五类是内容与配置的动态下发,改一句文案、调一个开关,不用重新走一遍提审流程。

这五件事里,前四件是“能力问题”,第五件是“节奏问题”。很多人只盯着前四件,觉得自己的工具类小程序不需要跨端同步、不需要权限,就判定不要后台,结果上线第一个月被“改个错别字要等三天”折磨得够呛。反过来也有人过度设计,一个本地计算器非要上一套完整后端,运维成本比开发成本还高。判断的关键不是“要不要”,而是逐条比对这五件事,看有几条是你真的碰上了。

1.2 三种“后台”形态的成本差着两个数量级,别一概而论

很多人排斥后台,排斥的其实是“买服务器、装环境、配域名、搞备案、盯监控”这一整套传统运维动作。但现在能叫“后台”的东西至少有三档,成本完全不在一个量级。

形态典型构成上手门槛适用规模主要成本项
免运维一体化后端平台自带的数据库 + 云函数 + 对象存储会写 JS 就能上手中小型、长尾流量按调用量和存储计费,前期几乎为零
托管型后端服务第三方提供的现成数据接口与账号体系配置为主,少量代码快速验证、活动页按套餐或调用量,功能受限于服务商
自建服务器自己买机器、部署服务、配域名证书需要运维能力高并发、强定制、有合规要求机器费 + 人力 + 时间

表格里最容易被忽略的是最后一列的“人力”。自建服务器真正的成本从来不是那台机器的钱,而是“半夜挂了谁起来看”的问题。一个两三个人的小团队,如果没有专职运维,自建后端带来的隐性成本往往在半年后集中爆发。我的经验是:日活没到需要认真算机器成本的时候,前两档永远优先。

1.3 一个反直觉的判断顺序:先定数据边界,再谈技术选型

大多数人是从技术侧出发的——“我会 Node,那就写个服务”“我不想学新东西,那就用本地缓存”。这个顺序反了。正确的顺序是先回答一个问题:这份数据的主人是谁。数据只属于当前这台设备上的这个用户,那它就是“私有本地数据”,本地存完全合理;数据需要在多个用户之间流转,或者需要在服务端做聚合统计,那它就是“共享数据”,绕不开一个中心化的存储。

我见过一个记账类小程序,前期所有账目都存本地,跑得挺好,后来想加一个“家庭共享账本”,一下子全乱套了——本地数据没有用户 ID 概念,没有归属关系,加共享功能等于推倒重来。所以判断数据边界的时候,不能只看“现在”,要往后看半步:这个功能未来半年最可能往哪个方向长。如果最可能的演进方向是“多人协作”或者“多端同步”,那从一开始就按共享数据的架构来设计,哪怕暂时只存在本地。

2. 六道判断题,五分钟内给自己的项目定性

下面这六道题是我自己用的清单,按顺序过一遍,基本能得出“完全不需要”“可以先不要但要预留”“必须有”三种结论之一。每道题我都标了“命中后的后果”,方便你权衡。

2.1 数据要不要离开这台设备

这是最硬的一条。判断方法很简单:把手机恢复出厂设置,或者换一台设备登录,你的用户会损失什么。如果答案是“什么都没损失”,那这份数据天然属于本地;如果答案是“我攒了半年的记录全没了”,那不管你现阶段用不用后台,都得有一个能把数据取回来的机制——它可以是云端的,也可以是用户自己导出再导入的,但绝不能只活在缓存里。

有个折中方案值得提一下:导出/导入 + 本地存储。用户点一下“备份”,把数据序列化成一个文件存到手机里,或者生成一段可复制的文本码。这个方案在很多工具类小程序里够用,成本几乎为零,缺点是用户体验稍微糙一点,而且要自己处理版本兼容(旧版本导出的格式新版本得能认)。如果你的用户是那种“愿意为省事多点两下”的人群,这个方案性价比很高。

2.2 有没有不能出现在客户端的秘密

第二道题是安全检查。把你准备打包上传的代码翻一遍,找这几样东西:第三方服务的密钥、数据库连接串、管理后台的地址、任何带“admin”字样的接口。只要找到一个,就必须有后台——不是因为功能需要,而是因为安全需要。前端代码是可以被完整下载并反编译的,混淆只能提高一点门槛,不能改变“密钥就是公开的”这个事实。

正确做法是把这类调用包一层:小程序调自己的云函数,云函数里带着密钥去调第三方,返回结果再给小程序。这样密钥留在服务端,客户端只拿到结果。云函数里还可以顺手做限流和参数校验,防止有人拿你的函数当免费代理刷第三方额度。这一层的代码量通常在几十行,但它是“能不能上线”和“上线会不会被刷爆”的分界线。

2.3 有没有用户关掉小程序之后还要发生的事

第三道题看时间维度。定时对账、到期提醒、超时自动取消、每天凌晨跑一次统计——这些动作的共同点是“用户不在场也得执行”。小程序本身没有常驻进程的能力,页面关掉就什么都不跑了,所以只要业务里存在这类需求,就必须有一个能被动触发的执行环境。

反过来,如果所有逻辑都是“用户点一下,立刻出结果”,那就不需要。做在线工具、计算器、图片压缩这类即时反馈型产品的人,在这一条上通常直接通过。需要注意的是“准实时”这一类需求,比如“用户下单后 30 分钟未支付自动取消”,很多人觉得可以让客户端自己计时,但用户一关小程序计时就断了。这种必须放服务端。

2.4 内容变更的频率,和提审周期的矛盾有多大

第四道题最容易被低估。小程序的发布需要经过平台审核,这个周期短则几小时,长则几天,而且你没法保证一次就过。如果你的产品里有大量“需要经常调整但不涉及逻辑”的内容——首页文案、活动banner、商品价格、开关配置、客服联系方式——那把这些东西硬编码在代码里,等于每次改一个字都要走一遍完整发布流程。

解决办法不一定非得是后台。轻一点的方案是把配置抽成一个远程 JSON 文件放在静态资源服务上,小程序启动时拉一次并缓存,改了文件立刻生效;稍重一点是用平台自带的云数据库建一张配置表,读一次缓存十分钟,运营在控制台改就行。这两个方案的成本差异不大,但都能把“改文案”从“发版”降级成“改配置”,值得优先做。

2.5 团队里有谁能接住凌晨三点的告警

第五道题是问人。自建后端意味着你要对可用性负责:机器会挂、磁盘会满、证书会过期、接口会被人刷。这不是技术问题,是排班问题。如果团队里没有人愿意也有能力在出故障时定位和恢复,那自建就不是一个选项,哪怕技术上完全可行。

这条我吃过亏。早年给一个小项目搭了套自建服务,觉得架构清爽、完全可控,结果某次磁盘写满导致接口全部超时,而我在外面没法处理,硬生生晾了几个小时。后来同样的项目改成免运维的一体化后端,虽然有些能力受限,但再也没出现过“半夜被叫起来”的情况。能用钱换掉的运维负担,在团队规模小的时候一定要换掉。

2.6 数据量和并发量到底在什么量级

最后一道是算术题,别拍脑袋。粗略估一下:日活 1000、人均每天产生 20 条记录、每条记录 500 字节,一天的增量大约是 10MB,一年 3.6GB。这个量级对任何形态的后端都是小菜。真正会卡住的是并发写入:如果某个时刻会有几百人同时写同一条数据,那就要考虑冲突处理,这跟存储介质关系不大,纯本地方案在这种情况下根本没法做。

算完这个数你大概率会发现,多数小程序的量级根本喂不饱一台最低配的服务器。所以“性能”通常不是选型的决定因素,别拿它当理由。真正决定选型的是前面五条里的安全、共享、定时、配置和人力。

3. 不搭服务器也能跑起来的四种形态

如果前面六道题过下来,结论是“暂时可以不要”或者“只要一小块”,那下面这四种形态基本能覆盖 80% 的场景。我把它们的边界写在每一条里,方便你直接对号入座。

3.1 纯本地存储型:工具、计算器、清单类的主场

这一类最纯粹:没有账号体系,没有云同步,所有数据都在用户设备上。典型代表是各种换算工具、图片处理、番茄钟、单机清单。它的实现要点只有一个——把本地存储封装好,别让页面直接摸缓存。我见过太多项目,页面里到处是读取缓存的调用,key 名散落各处,等哪天要换成远程接口,改起来像考古。

// data/store.js —— 统一的本地数据访问层(示意代码,各平台 API 名称略有差异) const PREFIX = 'v1:'; function read(key, fallback = null) { try { const raw = storage.getSync(PREFIX + key); if (!raw) return fallback; const parsed = JSON.parse(raw); return parsed && typeof parsed === 'object' && 'v' in parsed ? parsed.v : fallback; } catch (err) { // 缓存被污染或格式不兼容,直接回退,别让页面白屏 return fallback; } } function write(key, value) { try { storage.setSync(PREFIX + key, JSON.stringify({ v: value, t: Date.now() })); return true; } catch (err) { // 超限或序列化失败,返回 false 由调用方决定怎么提示 return false; } } module.exports = { read, write };

这里有两个细节值得说。一是key 加版本前缀,写成v1:xxx,将来数据结构变了直接换v2,旧数据自然失效,不用写迁移脚本。二是写入包一层对象,把值和写入时间一起存,方便做“多久没更新过”的判断,也方便后续上传时带上时间戳。这两点加起来不到十行代码,但能省掉后面很多麻烦。

3.2 一体化云端型:数据库、函数、存储一把梭

当需求变成“要跨设备同步”或者“要藏一个密钥”的时候,第一选择不是自建,而是平台自带的那套一体化后端。它的构成很固定:一个文档型数据库、一组可以被小程序直接调用的函数、一个对象存储放图片。这套东西的好处是账号体系是现成的——函数里能直接拿到平台已经验证过的用户标识,不需要你自己做登录、发令牌、校验签名。

// cloud/functions/saveRecord/index.js —— 云函数(示意) exports.main = async (event, context) => { // context.userId 由平台注入,客户端伪造不了 const userId = context.userId; if (!userId) { return { code: 401, msg: '未登录' }; } const { content, clientId } = event; if (typeof content !== 'string' || content.length > 500) { return { code: 400, msg: '内容不合法' }; } const now = Date.now(); // 服务端时间,客户端时间一律不信 await db.collection('records').add({ data: { userId, content, clientId, createdAt: now, updatedAt: now } }); return { code: 0, serverTime: now }; };

几个必须注意的点:客户端传上来的userId一律不认,只用上下文里注入的;时间戳一律用服务端生成,客户端时间可以随便改;clientId用来做幂等,因为网络重试很常见,同一笔数据可能提交两次,用客户端生成的唯一 ID 去重能避免重复记录。这三点是这类方案从“能跑”到“能上生产”的分水岭。

3.3 静态数据打包型:内容少、更新慢就用包体说话

有些小程序的内容完全是静态的,比如说明书、词库、菜品做法、故障排查手册。这类内容如果只有几百 KB,直接打进包体是最省事的——没有网络请求,没有加载态,离线也能用,体验反而最好。要点是按需分包,别一股脑塞进主包。主包体积通常限制在 2MB 量级,超了就得拆,把不同模块拆成子包,用户点到哪块下载哪块。

如果内容会周期性更新但又不频繁,可以用“包体内置一个基线版本 + 启动时拉一个增量 JSON”的组合。基线保证首次打开就能用,增量保证内容不过时。增量文件挂在静态资源服务上,改完上传即刻生效,不需要发版。这个方案我在几个内容型小程序里用过,效果不错,唯一要注意的是增量文件要做版本号和时间戳,避免浏览器或客户端缓存住旧版本。

3.4 借用现成服务型:把第三方当成临时后端

还有一种情况是“只差一点点后端能力”,比如需要一个简单的表单收集、一个留言板、一个活动报名。这时候专门搭一套后端显然不划算,借用现成的在线表单、在线表格作为数据源是常见做法:小程序提交时调一个上传接口,数据落到表格里,运营直接在表格里看。

这种做法在活动页、临时调研、内部工具里非常实用,上线速度以小时计。但它有明显的天花板:并发能力受限于服务商、数据结构改动麻烦、权限控制粗糙、数据导出后再处理成本高。我的建议是把它定位成一次性或短周期的方案,并且在代码里做好隔离——所有对第三方的调用集中在一个模块里,将来换成自己的接口时只改这一个文件。

4. 省掉后台的那笔账,往往在半年后才寄到

前面说的都是“可以不要”的情况,这一节说反面。临时方案最大的问题是它的代价不在当下显现,而是在用户量上来、需求变复杂之后集中爆发。下面这五个是我见过最多的“账单”。

4.1 密钥被打包带走,是翻车率最高的一种

前端代码是可以被完整下载的,这一点很多人知道,但真正意识到“我放在里面的密钥等于公开”的人不多。尤其是一些第三方服务的密钥,一旦泄露,别人可以拿着它消耗你的额度、调用你的付费接口,账单会以你意想不到的速度增长。

我见过一个案例:某小程序把某个服务的密钥写在了前端配置里,上线两个月后额度被刷光才发现。补救措施只有一条——立刻在服务商后台重置密钥,然后加一层自己的函数做中转。重置密钥这件事的代价是,所有已发布的老版本小程序立刻失效,必须紧急发版。这就是为什么我一直强调:只要涉及密钥,宁可多写三十行中转函数,也别图省事。

4.2 本地数据不设防,改个缓存就能绕过所有规则

本地存储对用户是完全开放的。稍微懂点技术的用户改一下缓存里的数值,就能把积分改成九万九、把会员状态改成永久。如果你的产品里有任何“虚拟资产”或者“权限等级”的概念,把它存在本地就等于没有。

判断标准很直接:这份数据被改了,会不会造成实际损失。记账工具的账目被改,损失的是用户自己,可以接受;签到积分被改,损失的是你,不能接受。凡是涉及权益、额度、等级的数据,哪怕只是个排行榜,也要放到服务端去判定。落地的成本其实不高——通常只需要一个“校验并写入”的函数,不需要完整后端。

4.3 改一句文案等一周,运营会先于代码崩溃

这条听起来不严重,实际折磨人。小程序发布要走审核,审核周期不受你控制。如果你的所有文案都硬编码在代码里,那意味着运营想改一个错别字、换一张活动图、调一下客服电话,都得走一遍完整发布流程,还要承担“这次审核被拒”的风险。

正确的做法是把所有“运营可调项”抽出来,集中放在一个配置模块里,这个模块的取值优先从远程拉取,拉不到再用默认值。代码大概长这样:

// config/index.js —— 运营配置读取(示意) const DEFAULTS = { homeBanner: 'default-banner.png', servicePhone: '000-00000000', showPromoEntry: false }; let cache = null; let fetchedAt = 0; async function getConfig() { const now = Date.now(); // 十分钟内不重复拉取,避免频繁请求 if (cache && now - fetchedAt < 10 * 60 * 1000) { return cache; } try { const remote = await request.get('/static/config.json'); // 静态资源即可 cache = Object.assign({}, DEFAULTS, remote); fetchedAt = now; } catch (err) { cache = cache || DEFAULTS; // 拉取失败也必须能用 } return cache; }

这段代码的价值不在技术难度,而在它把“改文案”从发版降级成了改文件。配置文件甚至不用数据库,放在静态资源上就行,改完立刻生效。默认值必须有,因为网络请求随时可能失败,不能让用户看到一个空白页。

4.4 换设备就丢数据,是一个几乎看不见的流失漏斗

用户换了手机,打开小程序发现数据全没了,多数人不会来投诉,他们直接走。这类流失在数据上看不出来,因为这些人本来就没留下什么痕迹。但对于有留存属性的产品——记账、健身记录、学习进度、收藏夹——这是实打实的用户损失。

这条的解法不一定是上完整后端。前面提过的“导出/导入”能救一部分;如果能接受一点成本,用一体化后端做一个“一键同步”更好。关键是在用户还没丢数据之前就让他知道数据会被保存,这个心理预期本身就值钱。

4.5 临时方案跑久了会长出獠牙

最后一笔账是迁移成本。临时方案用久了,代码会围绕它生长——页面里到处是本地读取,数据结构跟缓存格式绑死,ID 用的是自增数字,甚至有些逻辑假设“数据一定在本地”。等到真要接后端的时候,改动面会远超预期。

我在第 5 节会专门讲怎么规避这一点,核心就一句话:从第一天起就给数据访问留一层抽象,别让页面知道数据是从哪来的。

5. 一条可复现的演进路径:现在不要后端,但要留好接口

假设你现在判断“暂时不需要后台”,那接下来要做的不是简单地把数据塞本地,而是按一套“将来能平滑接上”的方式来做。这套路径我在几个项目里跑过,迁移那天的工作量能控制在一天以内。

5.1 数据访问层:让页面永远不知道数据从哪来

最核心的一条。页面里禁止出现直接的缓存读写,所有数据操作走一个统一的模块。这个模块对外暴露的接口是“业务语义”的,不是“存储语义”的——也就是说,暴露的是listRecords()而不是getStorage('records')。

// data/recordService.js —— 业务数据服务(当前本地实现) const store = require('./store'); const KEY = 'records'; async function listRecords() { return store.read(KEY, []); } async function addRecord(input) { const list = await listRecords(); const item = { id: input.clientId || ('local_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8)), content: input.content, createdAt: Date.now(), syncState: 'pending' // 预留:将来上传成功后改成 synced }; list.unshift(item); store.write(KEY, list); return item; } module.exports = { listRecords, addRecord };

注意这里有两个刻意的设计。一是所有方法都是 async,哪怕当前实现是同步的。这样将来换成网络请求时,调用方的await不用改一行。二是每条记录带一个id和一个syncState字段,id由客户端生成(而不是本地自增),保证将来上传到服务端时不会撞主键;syncState标记同步状态,迁移时用它来决定哪些数据需要上传。

5.2 接口签名怎么定,才能无痛替换

签名设计的原则是:站在业务角度描述操作,不暴露存储细节。举几个对比:

推荐写法不推荐写法原因
listRecords({ page, size })getStorage('records')将来分页要服务端支持,签名不用变
addRecord({ content })pushToArray('records', item)服务端会有自己的 ID 生成规则
removeRecord(id)filterArray('records', fn)删除在远端是软删,本地是硬删,语义要统一
syncAll()无迁移时需要一个统一入口触发上传

另外建议在服务层加一个开关,用配置控制走本地还是走远端。这样迁移可以灰度进行:先让一部分用户走远端,观察一段时间没问题再全量。开关本身不要复杂,一个布尔值加一个白名单就够了。

5.3 上线前必须补齐的三件事:ID、时间、冲突

哪怕决定不要后端,这三件事现在就要想清楚,否则将来迁移时会付出几倍代价。

ID 体系:客户端生成的 ID 必须全局唯一,别用自增数字。常见写法是时间戳 + 随机串,或者直接生成一个 UUID 风格的长串。服务端要接受客户端传来的 ID,用它做幂等键,而不是自己重新生成一个——否则同一条数据在本地和服务端会是两个 ID,对不上。

时间基准:所有“发生时间”以服务端时间戳为准。本地可以先记一个近似值,但一旦同步,以服务端返回的为准。这一点在做“最近记录”“按时间排序”的时候特别重要,用户改了系统时间就会导致排序错乱。

冲突策略:至少要定下一条规则——同一条数据在本地和远端都被修改过,听谁的。最常见的三种是“最后写入胜”“服务端优先”“字段级合并”。工具类产品用“最后写入胜”通常够了,但要在 UI 上给用户一点提示,比如“已在其他设备更新”。

5.4 迁移当天的操作顺序:先读后写、双写灰度、旧数据回填

真到了要接后端那天,按这个顺序走能最大限度降低风险。

第一步,先只把“读”切到远端,写还留在本地。这样做的好处是即使远端出问题,用户至少还能看到自己的本地数据,不会白屏。第二步,加双写:新数据同时写本地和远端,本地作为兜底缓存。这时候要处理幂等,用前面说的clientId去重,网络重试不会产生重复记录。第三步,做旧数据回填:扫一遍本地数据,把syncState为pending的批量上传,上传成功的标记为synced。回填要限速,别一次性把几千条全推上去。

整个过程建议留一个“同步状态”的页面给用户看,让他知道有多少条待同步。这不只是体验问题,也是你自己的排障入口——出问题时能看到卡在哪一步。

6. 几个具体踩过的坑,都是文档里不太会写的

最后这一节列几个具体问题,都是我在实际项目里遇到或者被同行问到的,属于“知道了能省半天”的那种。

6.1 图片先别急着塞进本地缓存

新手很容易把用户选的图片转成一段长文本(base64)直接存进缓存,觉得方便。问题有两个:一是缓存有容量限制,单个键通常在 1MB 量级,总共也就 10MB 量级,几张高清图就撑满了;二是这些长文本会随着数据一起被读写,序列化和反序列化的开销很大,列表一长就卡。

正确做法是把图片存成文件,缓存里只留路径。如果必须存到远端,用对象存储上传后拿回一个地址,缓存里存地址。顺带提一句主包体积:图片如果直接打进包体,很快会把主包撑到 2MB 量级的上限,该用网络图就用网络图,该用分包就分包。

6.2 同步读写会阻塞,列表操作要小心

本地缓存的同步接口在数据量大的时候会明显卡顿,因为它是在主线程上做序列化。我的经验是:超过一百条记录的列表,不要整块读写。可以按“索引 + 详情”拆开,索引只存 ID 和时间,详情一条一个键。这样列表页只读索引,速度快很多,详情页按需读单条。

另外写入要合并。用户连续操作时,不要每改一次就写一次,用一个短的延迟(比如 300 毫秒)合并多次写入,只落最后一次。这在拖拽排序、批量勾选这类场景里效果很明显。

6.3 云函数不是免费的午餐,冷启动和超时要有预案

用一体化后端的时候,函数调用有几个现实问题。一是冷启动:长时间没人调用之后,第一次调用会明显变慢,几百毫秒到一两秒都正常,如果这个函数里还串了别的请求,很容易超过默认超时时间。二是超时:默认超时通常只有几秒,做批量操作的时候必须显式调大,但也不能无脑调太大,会拖垮整体。

应对办法是:能一次请求拿完的数据别拆成多次;首屏依赖的数据在页面初始化时并行发起,别串行;关键路径上准备降级方案,函数失败时用缓存顶上,给用户一个“稍后重试”的提示而不是转圈到死。

6.4 客户端时间可以随便改,别拿它做业务判断

这个坑很隐蔽。用户把手机时间改到明天,你的“每日签到”就失效了;改成去年,你的“最近七天”统计就乱了。所有涉及时间判断的逻辑——签到、限时活动、排序、过期——都必须以服务端时间为准。

具体做法是:应用启动时拿一次服务端时间,记下本地时间与服务端时间的差值,之后所有“当前时间”都用本地时间加上这个差值来算。这个偏移量要定期刷新,因为用户可能中途改时间。真正做判定的时候(比如“这单是否超时”),仍然以服务端返回的结果为准,本地算的只是给用户看的展示值。

6.5 收集了信息就要说清楚,别等到审核被拒才补

如果小程序里有任何收集用户信息的行为——手机号、位置、相册、通讯录——都要在隐私说明里写清楚用途,并且在实际调用前给出提示。这一点现在审核越来越严,很多人是提交之后被打回来才想起来补。

我的建议是在项目一开始就列一张表:这个功能读了什么数据、存到哪里、存多久、谁能看到。这张表既能帮你应付审核,也能帮你判断“这个数据是不是真的需要收集”。很多时候列完会发现,有一半的数据根本不用收集,不收集就没有对应的合规负担,一举两得。

回到最开始那个朋友的问题:他那个小程序最终没买服务器,用的是平台自带的一体化后端,数据库加两个函数,一下午就跑通了。但他同时也把本地缓存改成了“离线兜底”的角色,而不是唯一的数据源。这个组合在我看来是多数小项目的合理答案——不是“要不要后台”的二选一,而是“核心数据放远端、体验兜底放本地”的分层。我个人在实际操作中的体会是,架构上多留一层抽象的成本,永远低于将来推倒重来的成本,哪怕你现在笃定这个项目永远只有几百个用户。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询