本期的用户故事,有幸邀请到云开发的资深用户分享使用云开发过程中的使用秘诀,以及背后的故事。(文末有彩蛋)
前言
如果编程不再需要处理繁琐的服务器问题,将是多么幸福的事情
自2009年毕业后,我就进入了互联网行业,我还记得当时的服务器是自己搭建的。与团队小伙伴自己购买大型服务器并置于北京市中心的机房,每次进入机房都要戴上鞋套,以免脚上的尘土洒落在机房里一层不染的地板砖上。
从那时起,维护服务器就成为了一场噩梦,虽然现在已经有腾讯云等云服务商,但是服务器的远程维护依然让我感觉有一种“牵挂”。那种半夜被叫醒,服务器“挂”了,然后你要赶紧起床去处理的感觉,我再也不想经历。
所以,当我第一次接触到微信小程序云开发的时候,我感觉这份“牵挂”终于放下了。云开发是一个后端即服务(BaaS)的解决方案,它让你可以专注于小程序的前端开发,而不用再去操心所有和服务器相关的事情。
使用云开发,不仅是技术层面的转变,更是生活方式的改变。你可以将更多时间投入到创新创造中。这给我一种侠客游走江湖的感觉,当我合上电脑时,我就能从"江湖"中彻底回到现实世界,与家人、孩子充分享受生活,不再有"牵挂"。这种在工作与生活之间自由切换,享受新的平衡,让我觉得写代码就像拿着手柄打游戏一样,充满了乐趣。
云开发带来的新体验
一键部署
云开发,并不是完全不需要服务器,而是服务器由微信自己去维护与管理,开发者只需要上传云函数代码即可。
云函数代码,其实就是一个Node.js项目,用户端小程序(前端)可以向微信云环境发起请求,微信云环境会负责调用你的云函数代码,然后返回结果给前端。
编写小程序代码和云函数代码、然后在微信开发者工具中一键上传(需分开操作),整个过程完全感觉不到有服务器的存在。
传统开发,要向数据库中写入数据,需要先在后端编写接口,然后前端调用接口。在云开发中,我们可以直接在前端读写数据库,根本不需要后端接口。
假如我们需要向商品表中插入一条数据,只需在前端这样写:
// 获得数据库引用
const db = getApp().cloud.database()
// 向products表中插入一条数据
db.collection('products').add({
data: {
name: 'iPhone 15',
price: 4999
}
})
而读取商品表中的数据,只需要这样写:
const products = await db.collection('products').get()
不需要知道数据库存储在哪里、用户端如何连接数据库、用户和数据库物理上的距离远不远、数据库是否备份、一秒钟有一万人访问能不能扛住等等。微信云环境都帮你很好的解决了。
云开发就好像一个封装好的魔法水晶球,只需要专注于代码,云环境会帮你解决其他问题
发现没有,前面读取数据库的代码中,没有任何鉴权相关的代码。在云开发中,所有的鉴权都是由微信云环境自动完成的。包括数据库权限、用户登录以及_openid的获取、支付接口的调用、云函数调用、文件的读取、所有API的调用,等等,都不需要我们自己去写鉴权逻辑。
由于所有的代码都运行在微信自己的服务器上,因此微信可以确保代码的安全性,我们只需要专注于业务逻辑的编写,不用担心自己的服务器被攻击,数据被盗取等问题。
在云开发中,前端和后端都是JavaScript(或TypeScript),这意味着你可以使用相同的语言编写前、后端代码。
云端return的数据,并不像传统服务器那样返回一个json字符串,而是直接返回一个对象,例如:
// 实现加法计算的云函数代码
exports.main = async (event, context) => {
const {x, y} = event
return {
sum: x + y,
}
}
而在前端代码中,可以直接这样调用:
const result = await wx.cloud.callFunction({
name: 'add', // 这里add是云函数的函数名称
data: {x: 1, y: 2}
})
console.log(result.sum) // 3
看,前后端已经被打通了,前端传给后端的数据是js的对象,后端返回给前端的数据也是js的对象。
而且,由于前、后端都使用JavaScript,那么前、后端就可以共用一些工具函数,例如数据库的读取操作(但要注意前、后端对数据权限的处理与前端不一样),字符串和时间的处理,等等。
如果原本有一段代码是运行在前端的,突然有一天想把它移动到云端(为了防止别人阅读代码,或前端性能不足等原因),几乎不需要做太大的改动,只需要复制粘贴到云函数中即可。
所谓的后端只是一个运行在云端的云函数,站在你的角度,你只是在写一个函数,而不是在写后端,更不需要学习任何的框架,云函数return返回前端需要的数据即可。从开发体验上来说,根本不觉得在写后端。
云开发计费模式
云开发是按照“基础套餐+按量计费”的方式收费的,有点像手机话费套餐,通常来说是用不完基础套餐资源的。如果某种资源的使用量超过了套餐限制,就需要额外后付费,而不是像传统服务器那样先购买配置。
我会根据自己的使用经验,重点介绍你可能关心的问题。
云开发基础套餐是19.9元/月,并且可以10个小程序共用一个套餐(小程序需同属于一人或公司)。
假设你有10个小程序,它们共用一个云开发环境,那么每个小程序的服务器成本可以低至2元/月。这种感觉有点像你进入一个客栈,店小二说“客官,我们这里吃一个饼是20元,吃十个也是20元,您要吃几个?”,不多吃几个都对不起自己。
前提是你的小程序用户量都不大,所有小程序消耗的资源总量不超过基础套餐的限制。
就像你的手机套餐有通话分钟数、短信次数、流量等,云环境也有调用次数、容量、流量、云函数资源使用量、文件存储、CDN等。
重点介绍的是“调用次数”,包含数据库的读写次数、云函数的调用次数、文件存储的读写次数。在每月基础套餐中,每月有20万次的“调用次数”额度,超出的部分会按照0.5元/万次另收费。
计算一下0.5元/万次的“调用次数”,假设平均每个用户每日会消耗20次调用次数,你的小程序每天有500人访问,每日消耗就是1万次,也就是0.5元,这个费用,让其中一个用户看一个视频广告就能赚回来(注意,实际情况中除了调用次数的费用,还可能产生其他费用)。
在上面的代码中,向数据库中写入一条数据会消耗一次“调用次数”,读取数据时也会消耗一次“调用次数”。
// 获取数据库引用不会消耗“调用次数”
const db = getApp().cloud.database()
// 下面的写入操作会消耗一次“调用次数”
db.collection('products').add({
data: {
name: 'iPhone 15',
price: 4999
}
})
// 下面的读取操作也会消耗一次“调用次数”
const products = await db.collection('products').get()
另外,每次使用callFunction调用云函数时也会消耗一次“调用次数”。
如果小程序在“调用次数”上超过了基础套餐的限制,那很可能是你对数据库的读写过于频繁或者说数据库设计不合理。
当我们使用云数据库的这种计费方式时,必须在编码习惯上有所转变,在设计数据库和编码时就要考虑“调用次数”。
举个例子,假设用户首次进入小程序时会从数据库读取小程序配置信息,例如首页的banner图、字体大小、导航栏的文案、提示弹窗文案等。通常做法会把这些配置都放在同一张表中,但有可能不会一次性读取所有配置数据,而是在使用到A数据时就读一下A数据,使用到B数据时就读一下B数据,并且下一次使用到相同的数据时,又会再读取一次。如果这样写代码,就会成倍的增加“调用次数”的消耗,那所谓的“云开发比传统服务器贵得多”就很可能发生。
作为程序员,我们按年支付购买的传统服务器,通常99%的CPU时间都是闲置的。因此,当你在对比云开发和传统服务器的费用时,你不能假设你可以100%利用传统服务器的资源(10%都不行),然后根据这个资源利用率来计算云开发的费用,这种对比方式没有意义。
未来是不可预测的,提前规划购买了高配置的服务器所带来的损失,可能比云开发的还要高。
云开发不支持脱离云环境在本地电脑上进行调试,必须有一个付费的云环境来进行开发和测试。
有些开发者会购买两个云环境,一个用于开发和测试,另一个用于生产环境,多一个开发环境意味着成本正价。在开发环境和生产环境之间的数据同步和代码同步是一个很繁琐的事情,一会切换到开发环境,一会切换到生产环境,这会让写代码这件原本很幸福的事变得很劳累,个人或小企业可以视情况自行决定是否增加,大企业用户无需考虑以上问题。
我个人的做法使用同一个云环境进行开发和测试。为了避免误删数据,需要对数据库的接口进行一定的封装,让开发环境自动访问xxx表,而生产环境自动访问p_xxx表(这里的p_前缀表示production)。
我的10个避免资源无效消耗的小妙招
1 合理设计数据库结构,减少读写次数
显示商品详情页时,要尽可能仅读取一次数据库,这就要求设计数据库时,把商品基本信息、商品图片、用户评论等都放在同个数据文档中
2 一次性读取较多数据
当显示一个列表页时,尽可能一次性读取1000条数据,然后分多次显示给用户
3 使用本地缓存
当用户首次进入商品列表页时,将商品列表数据缓存到本地,这样用户从商品详情页回到列表页时,就不需要再次读取数据库。可以在读取列表数据时,把详情页数据也一并读取,这样用户进入详情页时,就不需要再次读取数据库(单次读取数据的总大小有限制,以后详细介绍)
4 使用webp格式的图片
webp格式的图片比png、jpg小很多,这样可以减少网络流量的无效消耗
5 降低云函数的内存配置
云函数是按照“内存配置x运行时间”计算的,目前默认是256M,最可以手动降到128M
6 云函数中,用Promise.all并发执行,减少云函数的运行时间
有10个文件要下载,你可以使用Promise.all并发下载
7 把文件放在“静态存储”中
动态存储存储费用是静态存储的20倍
8 宁可存储冗余数据,减少数据库的“调用次数
商品的用户评论,可以把用户的头像、昵称和评论内容都存储在商品文档中,而不是存用户id,然后再用id去用户表中读取用户的头像、昵称
9 能不update的就不要update
如果用户修改了头像和昵称,商品评论中的头像和昵称不更新也可以。这不仅仅是为了减少“调用次数”,类似能不写的代码就不写是可以的
10 避免无效的重复计算
一个云函数会消耗10次“调用次数”,不同的用户调用该云函数时,返回的结果是一样的,可把结果缓存到数据库中,下次直接读取缓存结果
相信如果能做到以上10点,就能很好的避免资源无效浪费了。
享受你的编程体验
如果说你已经感受到使用云开发不需要和服务器打交道的幸福体验,并且也不再担心云开发的费用,但依然犹豫不决,那我相信一定是你担心从MySQL等关系型数据库迁移到文档型数据库会让你不习惯。
先说我个人的感受,在前、后端直接操作数据库给我带来的便利性,远远超过了那种不想改变编码习惯的排斥感。
如今,我们还有Copilot、ChatGPT等AI工具,当你想要插入或更新一条数据时,Copilot会一秒钟帮你写完数据库的API调用代码,而复杂的查询语句可以让ChatGPT或Claude帮你写,这大大的降低了我们学习文档型数据库的时间成本。
接下来通过一个案例,来看看小程序云数据库的优势。
假设我们有一个商品表products,并且商品的评论和其他信息是存储在同一个文档中的,如:
{
"_id": "id_1",
"name": "iPhone 15",
"price": 4999,
"comments": [
{
"content": "good",
"time": "2022-01-01"
},
{
"content": "bad",
"time": "2022-01-02"
}
]
}
那么,当我们要给商品添加一条评论时,只需要这样写:
// 获得数据库引用
const db = getApp().cloud.database()
const _ = db.command
db.collection('products').doc('id_1').update({
data: {
comments: _.push([{
content: 'very good',
time: new Date()
}])
}
})
关键是,上面这段代码,可以直接写在前端,不需要后端接口(云函数),当然你也可以很方便的复制到云函数中。
与使用MySQL关系型数据库的习惯不同,当我使用文档型数据库时,我会经常存储冗余数据。
这样做不仅仅是为了减少数据库的“调用次数”,更重要的是让写代码的体验变得更好。
举个例子,如果要删除一个商品以及这个商品的评论,如果使用关系型数据库,你至少要写两个SQL语句,一个删除商品,另一个删除商品的评论(如果你还有商品图片表、商品类型表、搜索关键词表、相关商品推荐表等,那就需要更多删除语句)。而在文档型数据库中,你只需要删除一个文档即可,如:
db.collection('products').doc('id_1').remove()
我个人认为,牺牲一点存储空间,换取写代码的体验,让产品尽快上线,是非常值得的。
说句扎心的话,你写的程序很可能没人用。既然是这样,那就在写代码这件事情上,尽可能少花时间,用最低的时间成本去验证产品的可行性,这才是最重要的。(如果你大型互联网公司就职,以上建议不适用。)
天下武功,唯快不破,在从0-1创造一个产品验证想法上,也是如此,云开发就是我们的凌波微步和无影手。
因此,数据库的设计要优先服务于写代码的体验,一句代码就能完成的不要写多句,能不update的就不要update,能不写的代码就不写,产品上线速度应该是你最关心的问题。
结语
快速迭代,验证想法
目前我也独立从设计到到开发完成了我的独立小程序绘图助手,用到了云开发的云数据库、云函数、云存储、静态存储、内容安全检测、语音转文字、多语言翻译的多种能力,并尝试推广
用最少的开发时间、最舒适的编码体验,完成产品最可能被用户需要的基础功能。去验证你的想法是否满足真实的用户需求,发布后立即进入到下一个产品的研发,不用管服务器端的琐事,真正把精力放在创造性的工作上,享受创造的乐趣,感受幸福的生活。
原创为腾讯云开发布道师 刘永辉
有奖活动
火热报名
腾讯云开发玩转小程序实战训练营
腾讯云开发者社区联合开发团队推出《腾讯云开发小程序实战训练营》,大咖导师实战引领,场景化教学助你轻松掌握。快速构建AI智能体、智能客服、营销活动等,即时对接微信开放能力,数据秒级融入。提升开发效率,加速业务迭代。点击阅读原文,立即报名,享免费体验,学习获结营证书,前40名学员更可获得丰厚奖励!
本文分享自 腾讯云开发CloudBase 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!