小程序云实现原理分析
小程序基于最新的Serverless架构,无论官方称之为什么,特征都属于Baas或者Serverless服务。
整个小程序云服务,包含了,客户端嵌入SDK,封装云函数上传命令,服务端主要在Faas云函数内部封装了openid、文件存储请求全局系统对象,方便大家请求微信与腾讯云接口, 云函数数据库操作,沿用了客户端SDK,由于JavaScript跨平台特性,js代码可以直接放到node里面执行,云函数里的wx-server-sdk,其实就是客户端的SDK。 客户端wx.cloud, 相当于微信开发工具写入了全局变量wx.cloud=wx-server-sdk库。
我们从客户端到服务端的顺序分析
客户端-》中间层-》数据库
1.客户端SDK
目前客户端大家是不需要自己引入的,直接写入开发工具对象,只要微信基础库版本到达 2.2.3 或以上的就可以使用
其实还有个服务端SDK,在云函数。
看不见的wx.cloud对象,cloud对象,是一个js SDK,通过jssdk赋值给全局对象, 由于云函数的数据库操作方法写法与客户端一致,我们可以猜测,客户端SDK,与云函数的wx-server-sdk库 是同一个库。
我们对比下2者的代码
- 客户端 (小程序开发工具)
db.collection('todos').doc('<some-todo-id>').get().then(res => {
// res.data 包含该记录的数据
console.log(res.data)
})
- 服务端 (Faas)
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
exports.main = async (event, context) => {
try {
return await db.collection('todos').doc('<some-todo-id>').get()
} catch(e) {
console.error(e)
}
}
核心代码
客户端
db.collection('todos').doc('<some-todo-id>').get()
服务端
return await db.collection('todos').doc('<some-todo-id>').get()
可以看到2者操作是相同的,只不过服务端用了es7的await异步对象,可以return 拿到结果集合。而客户端使用了 Promise风格,如果反编译微信开发工具,在wx.cloud对象里面,一定是可以找到大量与wx-server-sdk一模一样的代码。
2. 中间层封装
当我们开发登陆的时候,第一步需要拿到openid,客户端会请求云函数,云函数请求微信接口,最终返回openid,可我们看到云函数里面并不需要我们去请求微信的接口,而是直接event.userInfo.openId返回了openid。
看代码
exports.main = (event, context) => {
console.log(event)
console.log(context)
// 可执行其他自定义逻辑
// console.log 的内容可以在云开发云函数调用日志查看
return {
openid: event.userInfo.openId,
}
}
这里帮我们省略了很多代码,原本的流程是需要通过客户端code换区openid
接口地址:
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
抓包看下,测试出来,只要访问这个地址,即可访问openid
https://servicewechat.com/wxa-qbase/qbasecheckresult?event_id=HKnup_IMP8wWCsHwx0UyYsJMU0YPQm7u8eERg7Ll0wGB9CMSBtppMnu4P6Ytr6DFG2Vl_EGZS3nyEBw15OPCERLEi4Ok0HWC6g
返回结果
{
"base_resp": {
"ret": 0
},
"status": 1,
"content": "{\"openid\":\"oWPQH0WVoCkpiw3ErLYAIVnudjfA\"}",
"service_errcode": 0,
"service_errmsg": "",
"func_req_id": "0f9c7a3f-b63c-11e8-b8ac-525400e8849e"
}
可以看到, 只要带一个参数event_id,就可以拿到openid, 云函数return的内容,会在返回的content字段表现。
在请求从客户端,到达服务器之后,服务器获取到openid,记得这个openid比较特殊里有个情况是, 任何请求到服务器,都会获取openid, 第一次会从微信接口获取,写入到内存,第二次会直接从内存取。 这里用redis的情况可能性比较大。第二次请求直接取redis 值就可以了。 取到后写入event.userInfo对象。
所以在任何云函数里,只要event.userInfo.openId,你都可以拿到openid。授权后,event.userInfo还包含头像等其他信息。
其他云函数的操作,都封装在wx-server-sdk 这个代码,大家可以在每个云函数的依赖node_modules目录找到, 大家开发时遇到错误,也不要急,这里有个看错误技巧。
以 6 开始的是由微信服务器侧产生的错误码
以 5 开始的是由腾讯云侧产生的错误码
以 4 开始的是本地 SDK 产生的错误
3.数据库
文档很多地方使用了,文档,集合概念,操作数据库传入参数也是mongodb的风格,很明显的使用了非关系类型,Mongodb数据库。 每个应用一个Collection。 云数据相当于Mongodb UI控制台。连显示结构也没改。
相比之前的Wafer套件,可以说这次是一个全新的解决思路。跟Bmob一样实现一个人全栈小程序开发,唯一效率比Bmob低的是,这个人必须掌握nodejs,Bmob的服务如果做小程序,相比小程序云,大部分需求是不需要掌握nodejs。
总结:
整套可以理解为mongodb+Faas的结合,封装了数据存储操作SDK。 与阿里的Serverless服务一样,以Faas为核心, Faas目前内置只封装了openid,去掉了定时任务,网关等功能,任何功能自己通过faas去实现,但只限定小程序内调用。相比阿里的Serverless 更贴地气,因为这次有了客户端SDK,再加云函数SDK,让Serverless找了到落地的可能。
最后脑洞问题:能否自己用阿里云Serverless 搭建一个小程序云?
答案是可以的
mongodb+Faas目前阿里的都有,并且目前阿里Faas功能更强大,唯一差个小程序客户端操作数据库的SDK。未来有机会,可以出个教程如何使用Faas实现一套自己的小程序-云