文章目录
小程序云开发官网
小程序云开发w3c教程
serverless
字面理解
serverless = server + less (无服务器或者少服务器)
Serverless 的演进和形成主要经历
1、IaaS(Infrastructure-as-a-Service,提供物理机服务),
2、PaaS(Platform-as-a-Service,平台既服务,如阿里云,七牛,甚至我们自己的 nvm ,sce等),
3、CaaS(Container-as-a-Service,容器既服务,类似我们现在内部的 docker k8s服务),
4、FaaS(Function-as-a-Service,函数既服务,一个容器一个函数,使用时才消耗资源,不含存储,只包含逻辑),
5、Baas(Backend-as-a-Service,后端既服务,提供存储,数据库操作,消息转发,静态服务等云服务功能)
serverless = Faas + Baas
什么是云开发
云开发为什么会出现
之前想要让一个项目上线,需要很多事项
https:// 需要购买证书,正经的一些证书(通配型*)。申请到免费的,一年一续。
nginx,apache
python,php,nodejs,asp
cdn(预付费机制),带宽,几核CPU,多大内存
都需要花钱买
而云开发的出现--------省钱,省时间,省人力…
不再区分前后端,而是以业务分。只需要实现业务逻辑部分即可,后台的繁琐配置由云帮我们实现。
小程序传统后台和云开发比较
小程序云开发特点
无需搭建服务器,云调用
云函数内免鉴权、免签名计算、免 access_token调用小程序开放接口,包括服务端调用、获取开放数据等能力(如微信支付、获取运动步数)
云函数: 在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码。
云托管: 支持托管服务容器,不限框架和语言,常驻运行、天然鉴权,可快速进行业务迁移
内置JSON文档型数据库
云数据库: 文档型数据库,稳定可靠;支持在小程序端和云函数中调用。
存储: 云端文件存储,自带 CDN 加速,支持在前端直接上传/下载,可在云开发控制台可视化管理。
环境共享
环境:一个环境对应一整套独立的云开发资源,包括数据库、存储空间、云函数等资源。(默认可拥有最多两个环境,各个环境是相互独立的,建议一个创建为 test 测试环境,一个创建为 release 正式环境)
跨账号资源和能力复用,可授权云开发资源给其他小程序/公众号使用。
小程序云开发流程
注意:小程序云开发需要使用注册的小程序appid,测试和游客进入是没有云开发的功能。
1、创建工程
老项目改为云开发
project.config.json文件中手动添加
{
"miniprogramRoot": "miniprogram/",
"cloudfunctionRoot": "cloudfunctions/",
}
项目下新建miniprogram和cloudfunctions目录,将原先的内容移动到miniprogram目录下
新项目云开发
直接选择云开发创建项目
2、开通资源配额
可先选择资源均衡型免费开通,然后即可跳入管理后台页面
3、创建环境
一个小程序有两个免费配额环境,可将其一个置为测试环境,一个置为生产环境
管理后台设置–>环境设置 可对之前的环境进行修改
4、小程序端项目配置
config.js中配置云函数路由名称
const config = {
cloud_route: 'index'
}
export { config }
云函数请求封装utils/cloud-request.js
import { config } from "../config.js"
class CloudRequest{
constructor(){
this.cloud_route = config.cloud_route
}
request(params){
wx.cloud.callFunction({
// 要调用的云函数名称
name: this.cloud_route,
// 传递给云函数的参数
data: {
// 要调用的路由的路径,传入准确路径或者通配符*
$url: params.url,
data: params.data
},
success: res => {
params.success(res)
},
fail: err => {
console.log(err)
}
})
}
/*获得元素上的绑定的值*/
getDataSet(event, key) {
return event.currentTarget.dataset[key];
}
}
export { CloudRequest }
小程序目录下新建models文件夹,专门用来放请求云函数数据的逻辑
import { CloudRequest } from '../utils/cloud-request.js'
class CartModel extends CloudRequest {
_storageKeyName = 'cart';
constructor() {
super()
};
/**
* 获取数据
* @param {*} callBack
*/
getCartData(callBack) {
callBack(this.getCartDataFromLocal())
}
/**
* 修改数据并返回
* @param {*} item
* @param {*} callBack
*/
add(item, counts, callBack) {
callBack(this._localAdd(item, counts))
}
/**
* 修改数据
* @param {*} id
* @param {*} callBack
*/
addCounts(id, callBack) {
this._changeCounts(id, 1)
callBack()
}
}
export { CartModel }
5、云函数端项目配置
云函数的运行环境是 Node.js,我们可以在云函数中使用Nodejs内置模块以及使用 npm 安装第三方依赖
右击当前环境,新建Node.js云函数
可以对云函数的权限进行配置
修改之后右击文件上传并部署
使用 wx-server-sdk 提供的 getWXContext 方法获取到每次调用的上下文(appid、openid 等),无需维护复杂的鉴权机制,即可获取天然可信任的用户登录态(openid)。
微信里面的数据就存在云服务器内部,所以相关数据可以直接获取,不需要授权解密等相关步骤
一个小例子——获取微信步数
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
//event接收到的内容即为data传过来的数据
const {werundata} = event
console.log(werundata)
return {
werundata
}
}
小程序端调用
//获取微信运动步数
getWeiRunData:function(){
wx.getWeRunData({
success: (result) => {
console.log(result)
wx.cloud.callFunction({
name:"wxrundata",
data:{
werundata:wx.cloud.CloudID(result.cloudID)
},
success:(res)=>{
console.log(res)
}
})
}
})
}
调用第三方服务获取数据
在小程序端我们可以使用wx.request来与第三方api服务进行数据交互,那云函数除了可以直接给小程序端提供数据以外,能不能从第三方服务器获取数据呢?答案是肯定的,而且在云函数中使用HTTP请求访问第三方服务可以不受域名限制,即不需要像小程序端一样,要将域名添加到request合法域名里;也不受http和https的限制,没有域名只有IP都是可以的,所以云函数可以应用的场景非常多,即能方便的调用第三方服务,也能够充当一个功能复杂的完整应用的后端。不过需要注意的是,云函数是部署在云端,有些局域网等终端通信的业务只能在小程序里进行。
路由封装
一个用户在一个云环境中只能创建50个云函数
我们可以在一个云函数中创建多个路由,从而可以减少云函数个数
tcb-router基于 koa 风格的小程序·云开发云函数轻量级类路由库,主要用于优化服务端函数处理逻辑
安装
npm install --save tcb-router
// 云函数入口文件
const cloud = require('wx-server-sdk')
const TcbRouter = require('tcb-router');
const returnUtil = require('utils/ReturnUtil.js')
const banner = require('service/bannerService.js')
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
const app = new TcbRouter({ event });
// app.use 表示该中间件会适用于所有的路由
app.use(async (ctx, next) => {
ctx.data = {};
await next(); // 执行下一中间件
});
// 获取轮播
app.router('getBanner', async (ctx, next) => {
ctx.data = await _bannerItem(banner.getBanner())
ctx.body = await returnUtil.success(ctx)
await next();
})
return app.serve();
}
公共返回值封装utils/ReturnUtil.js
/**
* 成功调用
* @param {*} ctx
* @retuen
*/
const success = ctx => {
return {
code: 0,
message: 'success',
data: ctx.data
}
}
/**
* 调用失败
* @param {*} ctx
* @param {*} msg
* @retuen
*/
const error = (ctx,msg) => {
return {
code: 400,
message: msg,
data: ctx.data
}
}
module.exports={
success,
error
}
使用tcb-router时的一些说明:
通常情况下,我们不建议大家使用一个云函数来调用其他云函数这种做法,这种做法会导致云函数的执行时间会增加很多,而且还会耗费云函数的资源,我们可以使用tcb-router来处理需要跨云函数调用的情况;
值得注意的是,tcb-router会把所有云函数的承载放在一个云函数里,对并发有比较高要求的云函数建议不要把用tcb-router整到一个里面。每个云函数的并发数上限为1000,这本可以每秒处理十万级别的请求,但是如果把大量不同的云函数都集成到一个里面,尤其是一些耗时比较长的云函数会严重拖性能后退,而这些云函数都会共享这1000个并发,所以要注意根据情况来抉择了;
云函数会有一个冷启动时间(比如十分钟以上没人调用这个云函数,当再首次调用这个云函数会比较慢),当我们把多个功能相似、并发不会特别高(低于每秒几千)的云函数使用tcb-router集成到一个云函数里,这样就可以减少冷启动的可能性了;
6、数据库操作
云存储数据库创建及连接建立
数据库设计(主键、字段、数据类型、含义)
创建集合、导入数据
本地数据格式:json文件,内部每一组数据之间不用加逗号
{"_id":"9afd9b6a5d2182550289a5a349bffa78","show":true,"name":"test10","age":12.0,"sex":0.0}
{"_id":"f896855d5cfb5f6901c18d424a19b0bd","show":true,"name":"test02","age":20.0,"sex":1.0}
数据库操作封装
// 公共BaseModel
const cloud = require('wx-server-sdk');
// 环境
cloud.init({ env: process.env.Env })
const db = cloud.database();
/**
* 查询处理
* @param {object} model 集合名称
* @param {String} id 查询id
* @return {object|null} 查找结果
*/
const findById = (model, fields = {} , id ) => {
try {
return db.collection(model)
.doc(id)
.field(fields)
.get()
} catch (e) {
console.error(e)
}
}
/**
* 查询处理 带多条件的
* @param {object} model 集合名称
* @param {Object} [options={}] 查询条件
* @param {Number} [page] 开始记录数
* @param {Number} [size] 每页显示的记录数
* @return {object|null} 查找结果
*/
const query = (model, fields = {}, options = {}, page = 0, size = 10, order = { name: '_id', orderBy:'asc'} ) => {
try {
return db.collection(model)
.where(options)
.field(fields)
.skip(page)
.limit(size)
.orderBy(order.name, order.orderBy)
.get()
} catch (e) {
console.error(e)
}
}
/**
* 新增处理
* @param {object} model 集合名称
* @param {object} params 参数
* @return {object| null} 操作结果
*/
const add = (model, params) => {
try {
return db.collection(model).add({
data: params
});
} catch (e) {
console.error(e);
}
}
/**
* 编辑处理
* @param {object} model 集合名称
* @param {object} params 参数
* @return {object|null} 操作结果
*/
const update = (model, params) => {
// let id = params._id
// delete params._id
try {
return db.collection(model).doc(params._id)
.update({
data: params
})
} catch (e) {
console.error(e);
}
}
/**
* 删除结果
* @param {object} model 集合名称
* @param {String} id 参数
* @return {object|null} 操作结果
*/
const remove = (model, id) => {
try {
return db.collection(model).doc(id).remove()
} catch (e) {
console.error(e)
}
}
module.exports = {
query,
findById,
add,
update,
remove
}
操作外部数据库
如果你的项目已经使用了MySQL,数据库不方便迁移到云开发数据库或者你的业务更偏向于使用MySQL,在这种情况下,也是可以使用连接自建的MySQL数据库并把数据传到小程序端进行渲染的。
在服务器自建的MySQL或者在腾讯云等云服务公司购买的关系型数据库服务在开放了外部网络连接和IP白名单的情况下,都是可以使用云函数连接的,也就是说云函数是部署在公共网络之中的,只能访问公网的数据库资源(内网或本地的数据库是不行的),而你的数据库要能被公网访问就需要开放外部网络连接和IP白名单。不过云函数目前没有固定的IP,因此数据库需要添加的IP白名单列表会比较长。
如果你不想让数据库暴露在公网环境之下,但是又能被云函数访问,这里推荐使用腾讯云的私有网络。处于私有网络的腾讯云产品(比如云开发的云函数和腾讯云的MySQL数据库),可以通过腾讯云提供的对等连接进行互联。
私有网络服务创建及操作mysql数据库
7、数据存储
图片资源上传存储,可直接拖拽上传
8、本地调试
管理后台点击云函数,打开云函数列表进行本地断点调试,需要安装依赖
注意:
如本地调试已经打开,修改云函数无法直接生效,需要上传部署之后再重新开启本地调试
9、告警规则设置(自定义,以云函数为对象)
10、灰度发布
点击需要设置版本的函数后面的版本与配置,可以看到这个函数的版本情况,注意一下,latest是当前的最新版,如果没有设置过版本的话,也是目前接受请求的云函数版本
点击创建新版本,即可对当前的latest版本创建一个新版本,发布后,latest的快照版本即可创建成功
此时创建好的新版本还不能被前端访问,需要点击分配流量比例,设置访问的比例
默认的比例是latest占100%,在下拉框中选择刚才刚创建的版本,比例设置为100%,即可让用户此时访问刚刚创建的版本。只要设置好比例,就可以达到灰度发布的目的
11、运维监控(数据库、存储、云函数、短信等)
云函数目录说明
|–CloudFunction
|----config(相关参数配置,敏感信息)
|----fields(数据库中返回数据字段指定)
|----models(操作数据库封装,增删改查)
|----service(从数据库中获取相应数据)
|----action(接口数据组装返回)
|----test(接口服务测试)
|----utils(公共方法封装)
|----index.js(路由编写)