前言 随着 serverless 越来越火,基本大厂都使用云开发的技术,使自己的业务托管上云,开发者则大多把重心关注在业务的开发上,无需关注扩容等操作,一切交给云服务商即可,大大减少了开发部署等操作,而对于小程序云开发,开发者完全可以作为全栈工程师去开发项目(包括前端、后端、数据库-mongodb 等),无需搭建服务器,即可使用云端能力;云开发为开发者提供完整的原生云端支持和微信服务支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代,同时这一能力,同开发者已经使用的云服务相互兼容,并不互斥;
能力
作用
说明
云函数
无需自建服务器
在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码
数据库
无需自建数据库
一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库
存储
无需自建存储和 CDN
在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理
云调用
原生微信服务集成
基于云函数免鉴权使用小程序开放接口的能力,包括服务端调用、获取开放数据等能力
1. 新建云开发模板
也可以省略此步骤,直接在已有项目上开通和使用云开发。
新建项目选择一个空目录,填入 AppID(使用云开发能力必须填写 AppID),勾选创建 “云开发 QuickStart 项目”,点击创建即可得到一个展示云开发基础能力的示例小程序。该小程序与普通 QuickStart 小程序有以下不同需注意:
无游客模式、也不可以使用 测试号
project.config.json
中增加了字段 cloudfunctionRoot
用于指定存放云函数的目录
cloudfunctionRoot
指定的目录有特殊的图标
云开发能力从基础库 2.2.3 开始支持(覆盖率 97.3%,查看兼容性问题 )
从基础库 2.4.1 开始,在小程序插件中可以使用云开发,插件中使用云开发时,使用的是插件方的云资源而非宿主的云资源,在使用方式上与在小程序中使用无异。
2. 开通云开发、创建环境 创建了第一个云开发小程序后,在使用云开发能力之前需要先开通云开发。在开发者工具工具栏左侧,点击 “云开发” 按钮即可打开云控制台、根据提示开通云开发、创建云环境。默认配额下可以创建两个环境,各个环境相互隔离,每个环境都包含独立的数据库实例、存储空间、云函数配置等资源。每个环境都有唯一的环境 ID 标识,初始创建的环境自动成为默认环境。
注:AppID 首次开通云环境后,需等待大约 10 分钟方可正常使用云 API,在此期间官方后台服务正在做准备服务,如尝试在小程序中调用云 API 则会报 cloud init error:{ errMsg: "invalid scope" }
的错误
完成后我们就能看到控制台信息了
接着在 project.config.json 文件中配置云函数存放的位置
1 { "cloudfunctionRoot" : "cloudfunctions/" }
配置完后,在开发者工具中会出现当前环境的标示,这样就配置成功了;
然后在 app.js 中配置云开发的初始化方法:其中 env 为当前云开发的环境,不指定的话则默认为第一个创建的环境
注: 我们可以根据小程序开发环境的不同,去动态映射云开发的环境;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 App({ onLaunch: function ( ) { if (!wx.cloud) { console .error("请使用 2.2.3 或以上的基础库以使用云能力" ); } else { wx.cloud.init({ traceUser: true , }); } }, });
3. 体验云开发 3.1 常量 DYNAMIC_CURRENT_ENV
支持端:云函数 1.1.0
标志当前所在环境,注意该值不是当前所在环境 ID 的字符串,其值等价于 Symbol.for('DYNAMIC_CURRENT_ENV')
,是用于标志当前所在环境的。如在 init
中如果给 env
参数传该常量值,则后续的 API 请求会自动请求当前所在环境的云资源,如云函数 A 当前所在环境是 test-123
,则其接下来请求数据库、文件存储、云函数时都默认请求环境 test-123
的数据库、文件存储、云函数。
常量可用于:
cloud.init
的 env
参数
cloud.updateConfig
的 env
参数
各 API 的 config
参数中的 env
参数
注意事项:
3.2 云数据库 云数据库底层使用的是 mongodb,对于前端同学也不是很陌生;小程序调用数据库比较方便,可以直接在小程序 js 文件中调用(不像 uni-app 中,一定要在云函数中才能使用,比较恶心!); 首先按照下图先创建一个集合,作为测试我已经创建了一个名为 test 的集合
下面代码中,我们 onload 回调中我们向刚刚创建的 test 集合中添加了一个数据
1 2 3 4 5 6 7 8 9 10 11 onLoad: async function ( ) { const db = wx.cloud.database() await db.collection('test' ).add({ data: { a: 1 }, config: { env: 'test-123' } }) }
随后我们刷新控制台就能看到刚刚添加的数据啦
其他常用的方法,见官方文档
3.2 云函数 在云函数中使用 wx-server-sdk,需先调用初始化方法 init 一次,init 用于设置接下来在该云函数实例中调用云函数、数据库、文件存储时要访问的环境。
1 2 3 4 5 6 7 8 9 10 11 const cloud = require ("wx-server-sdk" );cloud.init({ env: "test-x1dzi" , }); let msg = await wx.cloud.callFunction({ name: "test" , data: {}, });
4 云开发实战-模糊图像高清处理 4.1 目的 解决模糊图片带来的不好体验,利用 AI 图片处理使其变高清;
4.2 技术栈 腾讯云 AI 图片处理 API、云调用、云函数、云储存
4.3 开发 1.申请开通腾讯云图像处理工作台;
2.开通完,等几分钟就可以看到控制台了;
3.然后点击后上角的接口文档
4.可以看到系统为你生成了一套代码,不过我们需要添加SecretId、SecretKey ,ImageUrl 为图片地址可以接受线上地址或者 Base64 地址,这个我们一会动态传递即可,返回的值是一个 base64 的地址;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 const tencentcloud = require ("tencentcloud-sdk-nodejs" );const TiiaClient = tencentcloud.tiia.v20190529.Client;const models = tencentcloud.tiia.v20190529.Models;const Credential = tencentcloud.common.Credential;const ClientProfile = tencentcloud.common.ClientProfile;const HttpProfile = tencentcloud.common.HttpProfile;let cred = new Credential("AKIDrjxxxxxx" , "iBRUIq5ssssss" );let httpProfile = new HttpProfile();httpProfile.endpoint = "tiia.tencentcloudapi.com" ; let clientProfile = new ClientProfile();clientProfile.httpProfile = httpProfile; let client = new TiiaClient(cred, "ap-beijing" , clientProfile);let req = new models.EnhanceImageRequest();let params = "{}" ;req.from_json_string(params); client.EnhanceImage(req, function (errMsg, response ) { if (errMsg) { console .log(errMsg); return ; } console .log(response.to_json_string()); });
5.然后我们需要把上面的代码放到云函数中,托管代码,然后前端去调用,首先创建一个新的云函数;
6.把代码粘贴到 index.js 中,稍加修改,用云函数包一下即可;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 const tencentcloud = require ("tencentcloud-sdk-nodejs" );const cloud = require ("wx-server-sdk" );cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }); exports .main = async (event, context) => { const TiiaClient = tencentcloud.tiia.v20190529.Client; const models = tencentcloud.tiia.v20190529.Models; const Credential = tencentcloud.common.Credential; const ClientProfile = tencentcloud.common.ClientProfile; const HttpProfile = tencentcloud.common.HttpProfile; let cred = new Credential("AKIDrjxxxxxx" , "iBRUIq5ssssss" ); let httpProfile = new HttpProfile(); httpProfile.endpoint = "tiia.tencentcloudapi.com" ; let clientProfile = new ClientProfile(); clientProfile.httpProfile = httpProfile; let client = new TiiaClient(cred, "ap-beijing" , clientProfile); let req = new models.EnhanceImageRequest(); const fileList = event.fileID; let params = '{"ImageUrl":"https://www.google.com/imgres?imgurl=https%3A%2F%2Fimg.iplaysoft.com%2Fwp-content%2Fuploads%2F2019%2Ffree-images%2Ffree_stock_photo.jpg&imgrefurl=https%3A%2F%2Fwww.iplaysoft.com%2Ffree-images.html&tbnid=vQjlM9KtkGsb_M&vet=12ahUKEwiY9Zfn3-frAhVG15QKHeudABMQMygAegUIARCeAQ..i&docid=JeaDEV9l4RQZhM&w=680&h=453&q=%E5%9B%BE%E7%89%87&ved=2ahUKEwiY9Zfn3-frAhVG15QKHeudABMQMygAegUIARCeAQ"}' ; req.from_json_string(params); function run ( ) { return new Promise ((resolve ) => { client.EnhanceImage(req, function (errMsg, response ) { if (errMsg) { console .log(errMsg); resolve(errMsg); } console .log(response.to_json_string()); resolve(response.EnhancedImage); }); }); } return { result: await run(), }; };
7.我们把代码粘贴到 index.js 中,然后开启本地调试,可以看到生成了 base64 地址,说明转换成功了
8.接下来我们需要把写死的图片通过前端传递过去,而且图片需要从本地选择,又图片转换功能不支持本地图片转换,需要线上地址,故用到了小程序端-云储存上传、云函数端-云储存下载;
流程: 前端选择图片=>把本地图片上传到云储存=>调用云函数传递云储存传递 fileID=>云函数调用云储存拿到真实线上地址=>调用 AI 接口=>返回转换后的地址给前端=>前端展示
前端选择图片
1 2 3 4 5 6 7 8 9 10 11 12 13 wx.chooseImage({ count: 1 , sizeType: ["compressed" ], sourceType: ["album" ], success: (res ) => { const tempFilePaths = res.tempFilePaths; this .setData({ ImageUrl: tempFilePaths[0 ], }); }, });
把本地图片上传到云储存&调用云函数传递云储存传递 fileID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 wx.cloud.uploadFile({ cloudPath: rdm + ".png" , filePath: this .data.ImageUrl, success: async (res) => { let msg = await wx.cloud.callFunction({ name: "Upload" , data: { fileID: [res.fileID], }, }); this .setData({ img: "data:image/png;base64," + msg.result.result, }); }, });
云函数调用云储存拿到真实线上地址=>调用 AI 接口=>返回转换后的地址给前端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const fileList = event.fileID;const result = await cloud.getTempFileURL({ fileList: fileList, }); let params = '{"ImageUrl":"' + result.fileList[0 ].tempFileURL + '"}' ;req.from_json_string(params); function run ( ) { return new Promise ((resolve ) => { client.EnhanceImage(req, function (errMsg, response ) { if (errMsg) { resolve(errMsg); } console .log(response.to_json_string()); resolve(response.EnhancedImage); }); }); } return { result: await run(), };