本文關鍵字:合併多個cloudfuncions為一個
在《打造小程序版本公號和自託管的公號(1)》中,我們談到了建立blog小程序的一些理論基礎和必要條件,現在,我們選擇一個這類小程序的源碼,來實踐一下:
我們選擇的是https://github.com/CavinCao/mini-blog/commit/7921a126122f4a980e1270475aeb22bb2d50c3d0,積分功能v2版本後面的一個修復版,為什麼選mini blog,因為它小。該有的都有,不該有的也沒有。很容易看清這類實踐的基本套路和這類程序的技術手法,下載源碼後打開微信開發IDE,掃碼IDE左上角小程序(開發社區號)綁定微信,,用IDE導入正確路徑下源碼,appid填你註冊過的小程序appid,因為miniblog使用的騰訊雲cloudbase託管的雲函數後端(當然miniblog還用了cb的數據庫),在點擊雲開發按鈕新建第一個數據庫或雲函數之前,它會自動幫你註冊或綁定已有的一個騰訊雲帳號,為了達到在已有帳號裡操作的效果,請保證預先處理你綁定IDE用的微信,它背後的某個騰訊雲號已有綁定該小程序作為登錄方式之一,這樣新建雲函或數據庫會自動在你已有的騰訊雲的cloudbase下進行,如果你使用了自動生成的騰訊雲號,那麼會得到一個新帳號已綁有小程序登錄但未綁定微信,需要二次登錄(先微信後小程序)才能進入帳號,解決方法是在那個新帳號裡綁定一次微信。
IDE打開,我們發現源碼有cloudfunctions雲函和miniprogram小程序,點雲開發,新建一個clodubase環境包月免費自動續費,登錄web版會發現用IDE建的是隻讀的而且與網頁端申請的那個免費可以共存,。接下來就是miniblog的安裝:有12個庫(access_token,mini_posts,mini_comments,mini_posts_related,mini_config,mini_logs,mini_formids,mini_member,mini_sign_detail,mini_point_detail,mini_subcribute,mini_share_detail),和8個函數,安裝12庫比較簡單,記得把權限全設為所有隻讀僅管理員和創造者修改,如果稍後你發現編出的小程序有各種BUG,那麼可能是12庫少安裝了某個或某些,或漏了權限沒改過來。然後在IDE裡定位到正確的cb部署環境,在IDE文件瀏覽器下點擊各個函數對應的文件夾,右擊部署(包括安裝node modules方式),一一給函數的版本管理->配置處添加Env:cb名的環境變量項,其中syncservice還需要提供內容同步的公號的AppId和AppSecret,adminservice還需要author:你的管理者微信的openid串(可在稍後調出小程序界面後切到/index/index/從ide的console中直接輸出的信息複製得到),miniprogram只需改下utils/config.js裡的env id到正確的cb名,還需要在IDE文件管理器中右擊index/posts/detail打到命令行安裝一個客端模塊:npm install wxa-plugin-canvas --production (設置,項目設置處勾上使用npm模塊),至於源碼用的各種templateid,由於是公共ID,所以不用修改。小程序前後端基本能一起工作起來了,執行一次synservices拉取一些測試文章(根據錯誤添加IP白名單)。
下面,我們來深度定製它:
將8個雲函數合併
由於部署8個雲函數帶來了管理上的困難,也顯得零散,所以我們把它合併成一個叫mini的雲函數中去,思路是先在cloudfunctions下新建mini,把各xxxservices中的config.json,package.json合併去除重複部分放到這,package-lock.json可刪掉,如以下修改:
config.json(json不允許註釋用時需要去掉//後的內容,下同)
{
"triggers": [
{
"name": "myTrigger",
"type": "timer",
"config": "0 30 8 * * * *"
}
],
"permissions": {
"openapi": [
"wxacode.getUnlimited",
"templateMessage.send",
"templateMessage.addTemplate",
"templateMessage.deleteTemplate",
"templateMessage.getTemplateList",
"templateMessage.getTemplateLibraryById",
"templateMessage.getTemplateLibraryList",
"subscribeMessage.send",
"subscribeMessage.getTemplateList",
"security.msgSecCheck" //注意這個
]
}
}
package.json:
{
"name": "mini",
"version": "1.0.0",
"runtime": "Nodejs8.9",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"date-utils": "^1.2.21",
"request-promise": "^4.2.4",
"towxml": "^2.1.4",
"hydrogen-js-sdk": "^2.2.0",
"request": "^2.88.0",
"wx-server-sdk": "^1.8.2" //注意這裡,提到了最高版
}
}
然後是重點整合部分,把各個index.js整成/mini下總的index.js(login/index.js已被如下融合,除外):
//////以下從各個index.js頭部整合到的全局變量
const cloud = require('wx-server-sdk')
cloud.init({ env: process.env.Env })
const rp = require('request-promise');
const dateUtils = require('date-utils')
const db = cloud.database()
const _ = db.command
const RELEASE_LOG_KEY = 'releaseLogKey'
const APPLY_TEMPLATE_ID = 'DI_AuJDmFXnNuME1vpX_hY2yw1pR6kFXPZ7ZAQ0uLOY'
//收到評論通知
const template = 'cwYd6eGpQ8y7xcVsYWuTSC-FAsAyv5KOAVGvjJIdI9Q'
const Towxml = require('towxml');
const towxml = new Towxml();
const COMMENT_TEMPLATE_ID = 'BxVtrR681icGxgVJOfJ8xdze6TsZiXdSmmUUXnd_9Zg'
//////以下整合的main,用了自建的route分發,實際上就是折分二個return:event,openid
exports.main = (event, context) => {
console.log(event)
console.log(context)
//註釋掉
//return {
// event,
// openid: wxContext.OPENID,
// appid: wxContext.APPID,
// unionid: wxContext.UNIONID,
//}
//這句重要
return router(event)
}
async function router(event) {
//從main中移到這裡
const wxContext = cloud.getWXContext()
//不需要了
//if (event.action !== 'checkAuthor' && event.action !== 'getLabelList' && event.action !== 'getClassifyList' && event.action !== 'getAdvertConfig') {
// let result = await checkAuthor(event)
// if (!result) {
// return false;
// }
//}
switch (event.action) {
//postsservices
case 'getPostsDetail': {
return getPostsDetail(event)
}
case 'addPostComment': {
return addPostComment(event)
}
case 'addPostChildComment': {
return addPostChildComment(event)
}
case 'addPostCollection': {
return addPostCollection(event)
}
case 'deletePostCollectionOrZan': {
return deletePostCollectionOrZan(event)
}
case 'addPostZan': {
return addPostZan(event)
}
case 'addPostQrCode': {
return addPostQrCode(event)
}
case 'checkPostComment': {
return checkPostComment(event)
}
//按葫蘆造樣,把memberservices,messageservices,adminservices,scheduleservices,syncservices,syncTokenservices其它case部分也弄到這
//注意這句
case default : return {openid: wxContext.OPENID}
}
}
.....
//再接下來就是從各個原xxxservice/index.js中移過來不包括開頭變量和main()的代碼的部分,直接複製即可。
然後就可以刪掉所有xxxservices文件夾了,客戶端修求主要集中在utils/api.js和app.js中。將它們改為全部callfunction("mini"),完工!!
將主題集成到首頁
由於主題被做成了一個與文章首頁和我的(後臺)並列的項。不爽。將其歸到首頁“最新,熱門,標籤”後的“主題”文章部分。
index.wxml,從topics.wxml中提取到這裡,介於搜索欄和文章列表之間
<!-- 專題列表 -->
<view class="cu-list menu card-menu margin-top" wx:for="{{classifyList}}" wx:key="idx" wx:for-index="idx" wx:for-item="item" id="{{item._id}}" data-tname="{{item.value.classifyName}}" bindtap='openTopicPosts'>
<view class="cu-item">
<view class="content padding-tb-sm">
<view>
<text class="cuIcon-title text-orange "></text>
{{item.value.classifyName}}
</view>
<view class="text-gray text-sm">
{{item.value.classifyDesc}}
</view>
</view>
</view>
</view>
由於展示是依靠js的,所以index.js:
data: {
classifyList: [],
posts: [],
.....
navItems: [{ name: '最新', index: 1 }, { name: '熱門', index: 2 }, { name: '標籤', index: 3 }, { name: '專題', index: 4 }],
.....
}
.....
// 如下設置內容,避免UI塊重疊
tabSelect: async function (e) {
......
case 1,2,3: {
that.setData({
.....
showHot: false,
classifyList: [],
showLabels: false, //case3時為true
posts: [],
......
})
.....
}
case 4: {
that.setData({
......
showHot: false,
showLabels: false,
classifyList: [],
posts: [],
.....
})
let task = that.getClassifyList()
await task
break
}
}
把函數getClassifyList: async function ()從/topics/topics.js中移到這,可把topiclist文件夾也移過來到index/下,修改相關路徑,之後可以刪掉topics文件夾了,
你還可以修改一些硬編碼的東西。
app.json: "navigationBarTitleText":
syncservice/index.js: totalComments: 0,//總的點評數 totalVisits: 100,//總的訪問數 totalZans: 50,//總的點贊數
pages/mine/mine.js,申請vip的提示語等
一些未來改進建議:
後臺管理,留言可以加一個是否開啟審核,“程序有一點點小異常,操作失敗啦',這類消息提示可以更精確。因為一般都是數據庫權限或templateid問題。
templateid位置:
adminservice/index.js : APPLY_TEMPLATE_ID
postservices/index.js評論:COMMENT_TEMPLATE_ID
utils/config.js:subcributeTemplateId
messageservice/index.js, template 評論被回覆模板ID
scheduleservice/index.js簽到提醒:SIGN_TEMPLATE_ID
mine/sign/sign.js:tempalteId
pages/mine/mine.js申請vip: tempalteId
整個過程都是在IDE模擬器中不斷的修改,調試,再調試。之後就是提交體驗了,提交體驗版本然後微信瀏覽基本接近以發佈後效果而IDE中的模擬器較之有一些效果體現不出來,還有,審核的時候有可能會說你動態網站不能通過很奇葩,那麼以cloudbase為後端意義何在?
下文我們將用fodi分開前後端的方式來劃分onemanager將它做成miniblog小程序的內容源或者給miniblog直接弄一個PC網站前端和pc網站後端寫作模塊。其實小程序和onemanger非常像。因為後者也是雲函數為後端,只不過一個定位網站前端,一個定位小程序前端。後端都是api服務。mini blog for wechat是直接利用cloudbase sdk調用雲函,天然鑑權請求,而onemanager的前端是利用普通網站提交,基於url route提交請求。fodi前後端利用更高級的ajax。這三者都有相似之處,其實cloudbase也可用於google flatter和mobile apps。
(此處不設回覆,掃碼到微信參與留言,或直接點擊到原文)