小程序云實現原理分析
小程序基于最新的Serverless架構渔呵,無論官方稱之為什么炬称,特征都屬于Baas或者Serverless服務膛壹。
整個小程序云服務堰塌,包含了赵刑,客戶端嵌入SDK,封裝云函數上傳命令场刑,服務端主要在Faas云函數內部封裝了openid般此、文件存儲請求全局系統(tǒng)對象,方便大家請求微信與騰訊云接口牵现, 云函數數據庫操作恤煞,沿用了客戶端SDK,由于JavaScript跨平臺特性施籍,js代碼可以直接放到node里面執(zhí)行居扒,云函數里的wx-server-sdk,其實就是客戶端的SDK丑慎。 客戶端wx.cloud, 相當于微信開發(fā)工具寫入了全局變量wx.cloud=wx-server-sdk庫喜喂。
我們從客戶端到服務端的順序分析
客戶端-》中間層-》數據庫
1.客戶端SDK
目前客戶端大家是不需要自己引入的瓤摧,直接寫入開發(fā)工具對象,只要微信基礎庫版本到達 2.2.3 或以上的就可以使用
其實還有個服務端SDK玉吁,在云函數照弥。
看不見的wx.cloud對象调衰,cloud對象颈走,是一個js SDK,通過jssdk賦值給全局對象怀吻, 由于云函數的數據庫操作方法寫法與客戶端一致影斑,我們可以猜測给赞,客戶端SDK,與云函數的wx-server-sdk庫 是同一個庫矫户。
我們對比下2者的代碼
- 客戶端 (小程序開發(fā)工具)
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風格柑蛇,如果反編譯微信開發(fā)工具,在wx.cloud對象里面驱闷,一定是可以找到大量與wx-server-sdk一模一樣的代碼耻台。
2. 中間層封裝
當我們開發(fā)登陸的時候,第一步需要拿到openid空另,客戶端會請求云函數粘我,云函數請求微信接口,最終返回openid痹换,可我們看到云函數里面并不需要我們去請求微信的接口征字,而是直接event.userInfo.openId返回了openid。
看代碼
exports.main = (event, context) => {
console.log(event)
console.log(context)
// 可執(zhí)行其他自定義邏輯
// console.log 的內容可以在云開發(fā)云函數調用日志查看
return {
openid: event.userInfo.openId,
}
}
這里幫我們省略了很多代碼娇豫,原本的流程是需要通過客戶端code換區(qū)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目錄找到再层, 大家開發(fā)時遇到錯誤贸铜,也不要急,這里有個看錯誤技巧聂受。
以 6 開始的是由微信服務器側產生的錯誤碼
以 5 開始的是由騰訊云側產生的錯誤碼
以 4 開始的是本地 SDK 產生的錯誤
3.數據庫
? 文檔很多地方使用了蒿秦,文檔,集合概念蛋济,操作數據庫傳入參數也是mongodb的風格棍鳖,很明顯的使用了非關系類型,Mongodb數據庫碗旅。 每個應用一個Collection渡处。 云數據相當于Mongodb UI控制臺。連顯示結構也沒改祟辟。
相比之前的Wafer套件医瘫,可以說這次是一個全新的解決思路。跟Bmob一樣實現一個人全棧小程序開發(fā)旧困,唯一效率比Bmob低的是醇份,這個人必須掌握nodejs,Bmob的服務如果做小程序吼具,相比小程序云僚纷,大部分需求是不需要掌握nodejs。
總結:
? 整套可以理解為mongodb+Faas的結合拗盒,封裝了數據存儲操作SDK怖竭。 與阿里的Serverless服務一樣,以Faas為核心陡蝇, Faas目前內置只封裝了openid侵状,去掉了定時任務赞弥,網關等功能,任何功能自己通過faas去實現趣兄,但只限定小程序內調用绽左。相比阿里的Serverless 更貼地氣,因為這次有了客戶端SDK艇潭,再加云函數SDK拼窥,讓Serverless找了到落地的可能。
最后腦洞問題:能否自己用阿里云Serverless 搭建一個小程序云蹋凝?
答案是可以的
mongodb+Faas目前阿里的都有鲁纠,并且目前阿里Faas功能更強大,唯一差個小程序客戶端操作數據庫的SDK鳍寂。未來有機會改含,可以出個教程如何使用Faas實現一套自己的小程序-云