端云一体的定位与适用场景
端云一体(Serverless 化的 BaaS)把服务器、数据库、文件存储与鉴权打包成云端服务,应用端通过 SDK 直接调用。开发者不需要买服务器、配域名、写部署脚本,就能拥有后端能力。
它适合三类场景:需要账号与多端同步的应用、数据以文档形式组织的轻业务系统、以及快速验证的产品原型。不适合的场景也很明确:需要复杂事务与强一致性、超低延迟、或需要深度定制运行环境的后端服务。
端云一体不是“没有后端”,而是“后端被抽象成了配置与函数”。你依然要设计数据模型、权限与错误处理,只是不用维护服务器。
判断标准可以简化为一句话:如果你的后端逻辑主要是增删改查加少量校验,端云一体能显著缩短交付周期;如果需要复杂的计算与调度,还是老老实实写服务端。
云函数:把后端逻辑写成函数
云函数是运行在云端的代码片段,按调用次数与运行时长计费。它承担三类职责:数据校验与写入、需要保密的逻辑(如调用第三方服务的密钥)、以及多端共用的业务规则。
// cloudfunctions/addTodo/index.ts —— 云函数入口
import { cloud } from '@hw-agconnect/cloud';
export async function handler(event: { title: string; uid: string }) {
const title = (event.title ?? '').trim();
if (title.length === 0 || title.length > 200) {
return { code: 400, msg: '标题不合法' };
}
const db = cloud.database();
const res = await db.collection('todo').insert({
title,
uid: event.uid,
done: false,
createdAt: new Date().toISOString(),
});
return { code: 0, data: { id: res.id } };
}
三个注意点:云函数里要再次做参数校验(不能只信任客户端);单次执行有时长上限,长任务要拆分或改为异步触发;把密钥放在云函数的环境变量里,绝不要打包进客户端。
云数据库:文档模型与查询
云数据库通常是文档型(类 JSON),没有固定表结构,写入时自动创建集合。灵活性的代价是需要你自己约束数据形状。
- 按查询设计先想清楚列表页要按什么排序、筛选,再决定字段与索引。
- 控制文档大小单个文档别塞数组大对象,超过几十 KB 就该拆子集合。
- 索引与配额常用查询条件要建索引,同时留意单次查询返回条数上限,用分页拉取。
安全规则是文档数据库的重中之重:必须按用户维度限制读写范围(例如只允许读写 uid 等于当前用户 ID 的记录),否则任何人都能拉走全库数据。这条规则要在控制台显式配置,并在上线前用另一个账号实测越权访问。
云存储与文件上传
云存储用于保存头像、图片、附件等非结构化文件。标准流程是:客户端申请上传凭证 → 直接上传到云存储 → 拿到文件 URL → 把 URL 写入数据库记录。
几点实践经验:上传前压缩图片(端侧压缩比云端处理更省流量);文件名用随机串避免重名与覆盖;大文件用分片上传并显示进度;删除记录时记得同时清理文件,否则会持续占用存储配额产生费用。
权限方面,尽量不要把存储桶设为公开可读。如果必须公开(如商品图),则要对上传做严格校验:文件类型白名单、大小上限、以及内容审核。上传接口是最容易被滥用的入口之一,一定要加频率限制。
端侧 SDK 接入与鉴权
端侧接入的第一步是初始化与鉴权。通常支持匿名登录、账号密码、第三方账号等多种方式,匿名登录适合先体验后注册的产品。
import { cloud } from '@hw-agconnect/cloud';
import { hilog } from '@kit.PerformanceAnalysisKit';
export async function initCloud(): Promise<void> {
await cloud.init({
context: getContext(), // 从 UIAbility 上下文中获取
});
const auth = cloud.auth();
if (!auth.getCurrentUser()) {
await auth.signInAnonymously(); // 匿名登录,后续可绑定正式账号
}
hilog.info(0x0000, 'Cloud', '当前用户: %{public}s', auth.getCurrentUser()?.getUid() ?? 'none');
}
export async function listTodo() {
const db = cloud.database();
const uid = cloud.auth().getCurrentUser()?.getUid();
const res = await db.collection('todo')
.where({ uid }) // 关键:始终带上用户维度条件
.orderBy('createdAt', 'desc')
.limit(20)
.get();
return res.data ?? [];
}
把 where({ uid }) 写在每个查询里是刻意为之的习惯:即使云端有安全规则,客户端也应当显式限定范围。双重保障,出错概率会低很多。
数据同步与离线优先设计
移动端网络不可靠,好的同步设计必须支持离线。核心思路是“本地先写、后台再同步”,让用户的操作立刻有反馈。
- 本地缓存:把数据存到端侧数据库或 Preferences,打开应用先渲染缓存,再拉取云端增量。
- 操作队列:离线时的增删改先入本地队列,联网后按顺序重放。
- 冲突处理:多端同时修改同一条记录时,用“最后写入胜出”或版本号比较;重要数据建议保留修改历史。
- 同步状态可视化:给用户明确的“已同步 / 同步中 / 待同步”提示,避免误以为数据丢失。
离线优先不是加个缓存,而是把“数据先落地、后同步”作为默认设计。用户不关心一致性协议,只关心点下去有没有反应。
实现时建议为每条记录加 updatedAt 与 version 字段,用它们做增量拉取与冲突判断,比全量拉取更省流量也更快。
实战:一个云同步的待办应用
把云函数、数据库与端侧调用串起来,实现“新增待办 → 云端写入 → 列表刷新”的完整链路。
import { cloud } from '@hw-agconnect/cloud';
// 端侧:调用云函数新增待办(云函数内部完成校验与写入)
export async function addTodo(title: string): Promise<boolean> {
const uid = cloud.auth().getCurrentUser()?.getUid();
if (!uid) { return false; }
try {
const res = await cloud.callFunction({
name: 'addTodo',
params: { title, uid },
timeout: 8000,
});
return (res as { code: number }).code === 0;
} catch (e) {
console.error(`云函数调用失败: ${(e as Error).message}`);
return false;
}
}
// 页面中:先乐观更新界面,再异步落库
@State items: Todo[] = [];
private async onCreate(title: string): Promise<void> {
const tempId = `local-${Date.now()}`;
this.items = [{ id: tempId, title, done: false } as Todo, ...this.items]; // 乐观更新
const ok = await addTodo(title);
if (!ok) {
this.items = this.items.filter(i => i.id !== tempId); // 失败回滚并提示
promptAction.showToast({ message: '保存失败,请稍后重试' });
}
}
这段代码的核心是“乐观更新 + 失败回滚”:用户点下按钮立刻看到新条目,后台失败再撤回并提示。相比“转圈等云端返回”,体验提升非常明显,代价是要认真处理回滚与去重。
成本、安全与发布注意事项
Serverless 的成本模型是按量计费,用得少很便宜,用得不小心会很贵。控制成本的手段有四个:列表分页而不是全量拉取、给查询建索引避免全表扫描、图片等静态资源走 CDN 与压缩、为异常调用加告警。
安全上要守住三条底线:数据库安全规则按用户维度隔离数据、云函数对入参做完整校验、密钥与敏感配置只存在云端。上线前务必用另一个账号模拟越权访问,确认拿不到别人的数据。
发布前还要确认:隐私政策中说明了数据采集范围与用途、用户数据删除通道可用、以及数据存储区域符合你的合规要求。这些内容在应用商店审核中经常被检查,提前准备好材料比事后补救省力得多。
端云一体让你更快上线,但也把“数据在谁手里、谁能读到”这个问题直接摆在了设计阶段。越早想清楚,返工越少。
到这里,鸿蒙开发的主线就闭环了:语言(ArkTS)、界面(ArkUI)、架构(Stage 模型)、工具链(DevEco Studio)与后端(端云一体)。接下来按你自己的项目方向深入即可。